zf2 annotation for select element - zend-form

I'm getting a bit confused with zf2 annotations, I created a few elements based on this tutorial:
/**
* #Annotation\Attributes({"type":"text" })
* #Annotation\Required(false)
* #Annotation\Options({"label":"Cardholder's Name: *:"})
*/
protected $cardholder;
For simple text all is working fine but I'm stuck when try to create a select element.
If you know any tutorial or github repo please let me know.

Problem was in view
so to get select you need
added example for validation and filtering
/**
* #Annotation\Attributes({"type":"text" })
* #Annotation\Options({"label":"Cardholder's Name: *:"})
* #Annotation\Required(false)
* #Annotation\Filters({"name":"StripTags"},{"name":"StringTrim"}})
* #Annotation\Validator({"name":"StringLength","options":{"min":"1", "max":"20"}})
*/
protected $cardholder;
/**
* #Annotation\Type("Zend\Form\Element\Select")
* #Annotation\Options({"label":"Description"})
* #Annotation\Attributes({"options":{"1":"Visa","2":"Maestro"}})
*/
protected $cardType;
and in view
<dt><?php echo $this->formLabel($form->get('cardholder')); ?></dt>
<dd><?php
echo $this->formInput($form->get('cardholder'));
echo $this->formElementErrors($form->get('cardholder'));
?></dd>
<dt><?php echo $this->formLabel($form->get('cardType')); ?></dt>
<dd><?php
echo $this->formSelect($form->get('cardType'));
echo $this->formElementErrors($form->get('cardType'));
?></dd>

Try this:
/**
* #Annotation\Type("Zend\Form\Element\Select")
* #Annotation\Required(false)
* #Annotation\Options({"label":"Cardholder's Name: *:", "value_options":{"1":"VISA", "2":"MASTER CARD", "3":"AMERICAN EXPRESS"}})
*/
protected $cardholder;

Try this
/**
* #Annotation\Type("Zend\Form\Element\Select")
* #Annotation\Required({"required":"false" })
* #Annotation\Filter({"name":"StringTrim"})
*
*
*/

Related

Suitescript 2.0 Adding 3rd party libraries

I have been watching the instructional videos on Youtube from Stoic Software and have tried uploading the following to my Netsuite account to test the creation of third party libraries:
/**
* Prompts the user if the current project has not been re-baselined in some time
*
* #copyright 2020 Stoic Software, LLC
* #author Eric T Grubaugh <eric#stoic.software>
*
* #NApiVersion 2.x
* #NScriptType ClientScript
* #NModuleScope Public
* #NAmdConfig ./amdconfig.json
* #appliedtorecord job
*/
define(["moment"], (moment) => {
const message = "Project has not been re-baselined in over two months.";
function pageInit(context) {
let lastBaseline = moment(
context.currentRecord.getValue({ fieldId: "lastbaselinedate" })
);
if (lastBaseline.isValid() && moment().diff(lastBaseline, "months") >= 2) {
alert(message);
}
}
return { pageInit };
});
This is the amdconfig.json file that sits in the same location as the script:
{
"paths": {
"moment": "./SuiteScripts/sdf_ignore/moment-with-locales.js"
}
}
When I try to create the script record, I get the following error:
Row 14 is the following: define(["moment"], (moment) => {
Can anyone see what the issue is?
Edit: thanks to #fullstack.studio I was able to upload the script.
I am getting the following error message though where it is not recognising the function:
the third party library I am trying to use is the one found under:
https://momentjs.com/
I use path without '.' => /SuiteScripts/.... The '.' is a ref to the current folder. And you may remove the .js ext.
"paths": {
"helper": "/SuiteScripts/My_Helper"
}
In the meta try to use 2.1 instead 2.x
/**
....
* #NApiVersion 2.1
....
*/

Make Kotlin models Serializable using swagger codegen

I am trying to generate my API logic using swagger codegen. However, I need to implement java.io.Serializable for the generated models.
I tried to add the following:
"serializeModel": true
to the config.json file, which didn't do anything.
My generated models come out like this:
package dms.models
/**
*
* #param id
* #param name
*/
data class GetCompanyResponse (
val id: kotlin.Int? = null,
val name: kotlin.String? = null
) {
}
But I need them to be like this:
package dms.models
import java.io.Serializable
/**
*
* #param id
* #param name
*/
data class GetCompanyResponse (
val id: kotlin.Int? = null,
val name: kotlin.String? = null
): Serializable {
}
My config.json looks like this:
{
"modelPackage": "dms.models",
"apiPackage": "dms.api",
"serializableModel": true
}
And the script I call to generate looks like this:
swagger-codegen generate -i $SWAGGER_URL -l $CLIENT -o $OUT_DIR -D modelDocs=$MODEL_DOCS -D apiTests=$API_TESTS -D apiDocs=$API_DOCS --config config.json
Does anyone know what I need to change in order for this to work?
I am using swagger codegen v3.0.25

API Platform and custom POST operation with custom body

I hope I'm right to ask this. I've looked at (almost) all similar concern but I ain't satisfied yet.
I'm working on a User entity and for days (weeks actually) now i'm trying to POST a user with a custom body. Here's some part of my entity User :
/**
* #ApiResource(
* normalizationContext={"groups"={"read"}},
* denormalizationContext={"groups"={"write"}},
* itemOperations={
* "get",
* "put",
* "delete",
* "get_active_user"={
* "method"="GET",
* "path"="/users/active/me",
* "controller"=UserReadAction::class,
* "defaults"={"_api_receive"=false},
* "swagger_context"={
* "parameters"={
*
* }
* }
* },
* },
* collectionOperations={
* "change_password"={
* "method"="POST",
* "path"="/users/active/changepassword",
* "controller"=UserChangePasswordAction::class,
* "normalization_context"={"groups"={"afup"}},
* "defaults"={"_api_receive"=false},
* "swagger_context"={
* "summary" = "Change user password",
* "parameters"={
* {
* "name" = "User",
* "in" = "body",
* "schema" = {
* "type" = "object",
* "properties" = {
* "password" = {"type"="string"},
* "nom" = {"type"="string"},
* }
* },
* "required" = "true",
* }
* },
* }
* }
* }
* )
* #ORM\Entity(repositoryClass="App\Repository\UserRepository")
* #ORM\Table(name="users")
*/
class User implements UserInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
* #Groups({"read", "write", "afup"})
*/
private $id;
Here is the controller:
namespace App\Controller\SDK;
use App\Entity\User;
use App\Service\SDK\UserService;
use Symfony\Component\Security\Core\Security;
class UserChangePasswordAction
{
public function __invoke(User $data)
{
var_dump($data);die;
}
}
And the services.yaml (some part) file
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/*'
tags: ['controller.service_arguments']
When I try this (see var_dump in controller), i get an error saying:
Cannot autowire argument $data of "App\Controller\SDK\UserChangePasswordAction()": it references class "App\Entity\User" no such service exists
I read the official doc and it seems that the _invoke method should automatically retrieve the entity. But it does not work for me.
Notice: I also defined a custom item operation "get_active_user" and it works fine.
Please I would like to understand :
what I did wrong,
how it actually works,
Thank you.
EDIT:
In the collectionOperation definition, i removed the following setting which means that we manually want to handle data (User) retrieval :
"defaults"={"_api_receive"=false},
Now, the controller returns an empty User entity, not an error. I still can't get the submitted data.
The edit of my question fix the concern. Actually, I just needed to remove this annotation from the POST opration definition :')
"defaults"={"_api_receive"=false},
Now, when I submit the data, I get them as on the following image :
This annotation is important when you write custom GET operation.
It is not working because that is a CollectionOperation. In this case, you can get the user through TokenStorageInterface
namespace App\Controller\SDK;
use App\Entity\User;
use App\Service\SDK\UserService;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class UserChangePasswordAction
{
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function __invoke(Request $request) //Get request if you want o keep args empty
{
var_dump($this->tokenStorage->getToken()->getUser());die;
}
}

NelmioApiDocBundle doesn't work “No operations defined in spec!” Symfony 3.4

I want to configure nelmio to my symfony 3 project. I installed the bundle but at the end I get a message of no operations defined !!!!
Whats's wrong? Any ideas?
/**
* List the rewards of the specified user.
*
* This call takes into account all confirmed awards, but not pending or refused awards.
*
* #Route("/product", name="product", methods={"GET"})
* #SWG\Response(
* response=200,
* description="Returns the rewards of an user",
* #SWG\Schema(
* type="array",
* #SWG\Items(ref=#Model(type=Reward::class, groups={"full"}))
* )
* )
* #SWG\Parameter(
* name="order",
* in="query",
* type="string",
* description="The field used to order rewards"
* )
* #SWG\Tag(name="rewards")
* #Security(name="Bearer")
*
*/
public function getProducts()
{
$product = $this->entityManager->getRepository(Product::class)->getProducts();
$productSerializer = $this->serializer->serialize($product, 'json');
return new JsonResponse($productSerializer);
}

Java jsch and resuming file upload after interruption?

I'm currently using in my code the com.jcraft.jsch library so that I can upload a file(or multiple files) from my local machine to a certain remote one. With file sizes of 5KB, 100KB, 200KB I don't have any concerns. However, I have one big concern when I tend to upload a file with file size 500MB , 1GB, 2GB and above, because there is always the possibility that the internet connection could fail on either side (local machine or remote)
I did a little research of my own and found that the Library has a field called RESUME, which refers to "file transfer mode" , but I haven't found an explanation about its proper use.
So my question is : Is there a way if the connection fails , after it is fixed, the file transfer continues from the point it was interrupted ?
I just "solved" this on my application and thought I would share what I learned.
I looked into how the RESUME is working and found that it depends on which methods you are using. For me I was using both a PipedInputStream and a PipedOutputStream since I might be transferring to/from local files or even both to/from remote servers.
I found that for me I provided my PipedOutputStream to the get method with no mode provided (defaults to OVERWRITE) and then provided my PipedInputStream to the put method with a parameter of RESUME. The put method progressed my InputStream the number of bytes equal to the current size of the file I am sending to.
This took a while as I was already progressing my PipedOutputStream X number of bytes and then the PipedInputStream was progressing another X bytes and I was getting significant gaps. I found this out by looking at the ChannelSftp source code
Of course this will be different if you are not doing the exact same thing as me, but if your source or destination are local you may not need to worry about that. I would try looking at the source code if you can't figure out how you are doing it.
I am using Grails so this may not work exactly for you, but here is what I did
/*
* This was initially copied from
* <a href="http://www.intelligrape.com/blog/2013/04/04/using-ftp-with-grails/">
* http://www.intelligrape.com/blog/2013/04/04/using-ftp-with-grails/</a> for
* the basic structure. JavaDoc and additional method were added as needed.
*
* #author Puneet Behl
* #author jonathan.tinsman
*/
class FtpService {
/**
* Gets the file from the server and loads it into the provided output stream
*
* #param outputStream
* - the output stream to have the file loaded to
* #param fileName
* - the desired file
* #param ftpCredential
* -the server credentials
*/
def load(OutputStream outputStream, String fileName, FtpCredential ftpCredential) {
connect(ftpCredential) { ChannelSftp sftp ->
sftp.get fileName, outputStream, new FtpMonitor()
}
}
/**
* Writes the file on the server
*
* #param inputStream
* - the input stream for writing
* #param fileName
* - the file name
* #param mode
* - the mode for the transfer (defaults to {#link ChannelSftp#OVERWRITE}
* #param ftpCredential
* - the server credentials
*/
def save(InputStream inputStream, String fileName, Integer mode = ChannelSftp.OVERWRITE, FtpCredential ftpCredential) {
connect(ftpCredential) { ChannelSftp sftp ->
sftp.put inputStream, fileName, mode
}
}
/**
* Transfers the file from the input server to the output server.
* <p>
* The usage of {#link PipedInputStream} and {#link PipedOutputStream} is
* from OsterMiller.org
*
* #param fileName
* - the file name
* #param inputFtpCredential
* - the input server
* #param outputFtpCredential
* - the output server
* #param mode
* - the mode for the transfer (defaults to {#link ChannelSftp#OVERWRITE}
*/
def transfer(String fileName, FtpCredential inputFtpCredential, FtpCredential outputFtpCredential, Integer mode = ChannelSftp.OVERWRITE) {
// To change the size of the buffer, add an int with the desired pipe
// size. The default is 1024
PipedInputStream input = new PipedInputStream();
PipedOutputStream output = new PipedOutputStream(input);
// Starting in different threads so they do not deadlock each other
new Thread(
new Runnable(){
public void run(){
new FtpService().load output, fileName, inputFtpCredential
}
}
).start();
/*
* only passing the mode to the "save" as the save will progress the
* input stream on it's own.
*
* If we pass the mode to the "load" method, then there will be a gap
* in the data as the "load" will progress the stream xx bytes and the
* "save" will progress it another xx bytes (the size of the existing
* file).
*/
save input, fileName, mode, outputFtpCredential
}
/**
* Connect to the server and call the provided ChannelSftp Closure.
*
* #param ftpCredential
* - the server to connect to
* #param closure
* - the closure to call
* #param disconnectOnFinish
* - to disconnect the Session when the Closure is done (defaults to true)
*/
private def connect(FtpCredential ftpCredential, Closure closure, boolean disconnectOnFinish = true) {
Session session = null
ChannelSftp sftp = null
try {
JSch jSch = new JSch()
session = jSch.getSession ftpCredential?.username, ftpCredential?.server, ftpCredential?.port
session.setConfig "StrictHostKeyChecking", "no"
if (ftpCredential?.password) {
session.password = ftpCredential?.password
} else {
File keyFile = new File("${grailsApplication.config.pathToKeyFile}")
jSch.addIdentity(keyFile?.absolutePath)
}
session.connect()
Channel sFtpChannel = session.openChannel "sftp"
sFtpChannel.connect()
sftp = sFtpChannel as ChannelSftp
sftp.cd ftpCredential?.remoteBaseDir
closure.call sftp
} catch (Exception ex) {
ex.printStackTrace()
} finally {
if (disconnectOnFinish) {
sftp?.exit()
session?.disconnect()
}
}
}
}