I'm struggling with getting my custom validator to work.
The thing is I have a custom form element that uses a custom validator.
But when field is being created the ValidatorPluginManager fails to find my custom validator.
Now I know that it's a scope issue but I can' resolve it.
Error message:
A plugin by the name "AliasExists" was not found in the plugin manager Zend\Validator\ValidatorPluginManager
Validator code:
class AliasExists
extends AbstractValidator
implements AdapterAwareInterface
{
use AdapterAwareTrait;
const NOT_UNIQUE = 'notUnique';
/**
* Validation failure message templates definition
*
* #var array
*/
protected $messageTemplates = [
self::NOT_UNIQUE => "Entry with alias %value% already exists",
];
/**
* #var string
*/
protected $table;
/**
* #var Select
*/
protected $select;
/**
* #var string
*/
protected $categoryField = 'category';
/**
* #var int
*/
protected $categoryValue;
public function __construct($options)
{
parent::__construct($options);
if ($options instanceof Traversable) {
$options = ArrayUtils::iteratorToArray($options);
} elseif ($options instanceof Adapter) {
$temp = [];
$temp['adapter'] = $options;
$options = $temp;
} else {
if (func_num_args() > 1) {
$options = func_get_args();
$firstArgument = array_shift($options);
if (is_array($firstArgument)) {
$temp = ArrayUtils::iteratorToArray($firstArgument);
} else {
$temp['table'] = $firstArgument;
}
if (!empty($options)) {
$temp['adapter'] = array_shift($options);
}
$options = $temp;
}
}
if (array_key_exists('table', $options)) {
$this->setTable($options['table']);
}
if (array_key_exists('adapter', $options)) {
$this->setAdapter($options['adapter']);
}
}
public function isValid($value, $context = null)
{
if (null === $this->adapter) {
throw new \RuntimeException('No database adapter set.');
}
if (empty($this->table)) {
throw new \RuntimeException('Table has not been set.');
}
$valid = true;
$this->setValue($value);
if ($context) {
// TODO
}
$result = $this->query($value);
if (!$result) {
$valid = false;
$this->error(self::NOT_UNIQUE);
}
return $valid;
}
public function getSelect()
{
if ($this->select instanceof Select) {
return $this->select;
}
$select = new Select();
$table = new TableIdentifier($this->table);
$select->from($table);
$select->where->equalTo(
'alias',
null
);
if (!empty($this->categoryField) && !empty($this->categoryValue)) {
$select->where->equalTo(
$this->categoryField,
$this->categoryValue
);
}
$select->columns(['id']);
$this->select = $select;
return $this->select;
}
/**
* Returns the set adapter
*
* #return Adapter
*/
public function getAdapter(): Adapter
{
return $this->adapter;
}
/**
* Sets a (new) DB adapter
*
* #param Adapter $adapter
* #return self Provides a fluent interface
*/
public function setAdapter(Adapter $adapter)
{
return $this->setDbAdapter($adapter);
}
/**
* Returns the set table
*
* #return string
*/
public function getTable(): string
{
return $this->table;
}
/**
* Sets a (new) table
*
* #param string $table
* #return self Provides a fluent interface
*/
public function setTable(string $table)
{
$this->table = $table;
$this->select = null;
return $this;
}
/**
* #return string
*/
public function getCategoryField(): string
{
return $this->categoryField;
}
/**
* #param string $categoryField
*/
public function setCategoryField(string $categoryField)
{
$this->categoryField = $categoryField;
}
/**
* #return int
*/
public function getCategoryValue(): int
{
return $this->categoryValue;
}
/**
* #param int $categoryValue
*/
public function setCategoryValue(int $categoryValue)
{
$this->categoryValue = $categoryValue;
}
protected function query($value)
{
$sql = new Sql($this->getAdapter());
$select = $this->getSelect();
$statement = $sql->prepareStatementForSqlObject($select);
$parameters = $statement->getParameterContainer();
$parameters['where1'] = (string)$value;
$result = $statement->execute();
return $result->current();
}
}
Validator factory:
class AliasExistsFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$db = $container->get(AdapterInterface::class);
return new AliasExists($db);
}
}
Custom form element code:
class Alias
extends Text
implements InputProviderInterface
{
protected $attributes = [
'name' => 'alias',
'required' => 'required',
'class' => 'form-control',
];
protected $label = 'Alias';
public function __construct($name = null, array $options = [])
{
parent::__construct($name, $options);
$this->setAttribute('id', $this->getName());
}
public function getInputSpecification()
{
return [
'name' => $this->getName(),
'required' => true,
'filters' => [
['name' => 'StringTrim'],
['name' => 'StringToLower'],
],
'validators' => [
[
'name' => 'NotEmpty',
'options' => [
'type' => 'string'
],
],
[
'name' => 'Regex',
'options' => [
'pattern' => '/^[0-9a-zA-Z-_]+$/',
'messages' => [
Regex::NOT_MATCH => 'Only numbers, underscore, dash and characters from A to Z are allowed'
],
],
],
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 255
],
],
[
'name' => 'AliasExists', <--- Custom validator
]
],
];
}
}
module.config.php
'form_elements' => [
'factories' => [
Form\Element\Alias::class => InvokableFactory::class,
],
],
'validators' => [
'factories' => [
Validator\AliasExists::class => Factory\AliasExistsFactory::class,
],
'aliases' => [
'AliasExists' => Validator\AliasExists::class,
]
]
Controller factory that instantiates form that has this custom field:
class EditControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$formManager = $container->get('FormElementManager');
$form = $formManager->get(ArticleForm::class);
return new EditController($form);
}
}
The only way I can get my custom validator to work is (as found in this answer Possible to create a factory to instantiate custom Form validators?) is to set validator chain in controller factory that instantiates form but its an overkill to have to do this in every controller factory that could possibly have a form that uses this field that has custom validator in it.
Related
Remember this is codeigniter 4.
I need help in here. I am learning to implement about the RestFul API in codeigniter 4.
Below is my detail code.
Routes :
$routes->resource('ApiManageMaintenance', ['controller' =>'App\Controllers\ApiData\ApiManageMaintenance']); // get, put, create, delete
ApiManageMaintenance.php :
<?php
namespace App\Controllers\ApiData;
use App\Controllers\BaseController;
use CodeIgniter\RESTful\ResourceController;
class ApiManageMaintenance extends ResourceController
{
function __construct()
{
$model = new Dennis_setting_model();
}
// equal to get
public function index()
{
$Medoo = new \App\Models\Dennis_medoo_model();
$result = $Medoo->SelectAllMaintenance();
$response = [
'status' => 200,
'error' => null,
'messages' => 'Pull Data Successfull',
'data' => $result
];
return json_encode($response);
}
// equal to post
public function create() {
$version = $this->request->getVar('version');
$reason = $this->request->getVar('reason');
if ($version == "" || $reason == "") {
$response = [
'status' => 102,
'error' => 'Data Error',
'messages' => 'Data Not Valid',
'data' => null
];
return json_encode($response);
}
$array = array ('version' => $version,
'reason' => $reason
);
$Medoo = new \App\Models\Dennis_medoo_model();
$Medoo->InsertNewMaintenance($array);
$response = [
'status' => 200,
'error' => null,
'messages' => 'Create New Maintenance Successfull',
'data' => null
];
return json_encode($response);
}
// equal to get
public function show($id = null) {
$Medoo = new \App\Models\Dennis_medoo_model();
$result = $Medoo->SelectAllMaintenance();
$response = [
'status' => 200,
'error' => null,
'messages' => 'Pull Data Successfull',
'data' => $result
];
return json_encode($response);
}
// equal to put
public function update($id = null) {
$data = $this->request->getRawInput();
$data['id'] = $id;
$response = [
'status' => 200,
'error' => null,
'messages' => 'Update Data Successfull',
'data' => null
];
return json_encode($response);
}
// equal to delete
public function delete($id = null) {
$Medoo = new \App\Models\Dennis_medoo_model();
$Medoo->DeleteMaintenance($id);
$response = [
'status' => 200,
'error' => null,
'messages' => 'Delete Data Successfull',
'data' => null
];
return json_encode($response);
}
}
Config Filter.php
<?php namespace Config;
use CodeIgniter\Config\BaseConfig;
class Filters extends BaseConfig
{
// Makes reading things below nicer,
// and simpler to change out script that's used.
public $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
'toolbar' => \CodeIgniter\Filters\DebugToolbar::class,
'honeypot' => \CodeIgniter\Filters\Honeypot::class,
'auth' => \App\Filters\Auth::class,
'authaccess' => \App\Filters\AuthAccess::class
];
// Always applied before every request
public $globals = [
'before' => [
//'honeypot'
'csrf' => ['except' => [
'api/ApiManageMaintenance/delete'
]
]
],
'after' => [
'toolbar',
//'honeypot'
],
];
// Works on all of a particular HTTP method
// (GET, POST, etc) as BEFORE filters only
// like: 'post' => ['CSRF', 'throttle'],
public $methods = [
];
// List filter aliases and any before/after uri patterns
// that they should run on, like:
// 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']],
public $filters = [];
}
Note : I am using thirdparty database library => Medoo, So just ignore it. I am not using the build in framework database query in codeigniter for some reason because Medoo is looking light and simple for me.
Then For Is Working :
Restful API : create => Working => Test With Postman Method : POST
Restful API : show / index => Working => Test With Postman Method : GET
https://somedomain.id/index.php/ApiManageMaintenance
Then For Not Working :
Restful API : update => Not Working => Test With Postman Method : PUT
Restful API : delete => Not Working => Test With Postman Method : DELETE
https://somedomain.id/index.php/ApiManageMaintenance/7
Restful API delete and update both give me an error when try in postman :
403 - Forbidden: Access is denied. You do not have permission to view
this directory or page using the credentials that you supplied.
I also add execption in config => filter.php
public $globals = [
'before' => [
//'honeypot'
'csrf' => ['except' => [
'api/ApiManageMaintenance/delete'
]
]
],
];
I dont really understand the config filter.php but it seem this line of code will make the api delete working.
'csrf' => ['except' => [
'api/ApiManageMaintenance/delete'
]
]
Now my question are :
Is there any specific setup or configuration I miss or I need to do
for Restfu API to make API Restfull working ?
Any help from this community is very appreciate.
The Answer :
Create File Filter in Folder Filters in Codeigniter 4
Put this code :
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
use Codeigniter\API\ResponseTrait;
use Config\Services;
use Exception;
class FilterBasicAuth implements FilterInterface
{
use ResponseTrait;
public function before(RequestInterface $request, $arguments = null)
{
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
die();
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Do something here
}
}
The main code is :
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, Authorization");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
$method = $_SERVER['REQUEST_METHOD'];
if ($method == "OPTIONS") {
die();
}
Then in config Filters.php
put and add aliases this code :
public $aliases = [
'cors' => \App\Filters\FilterBasicAuth::class,
];
Note :
I use filter name FilterBasicAuth. You can change to yours and
make sure in the aliases change the name too.
Thats All.
okay the best way implelemnet restfull apici4
api ctl
<?php
namespace Modules\Shared\Controllers;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*
* #package CodeIgniter
*/
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\RESTful\ResourceController;
use Modules\Auth\Config\Services;
use Myth\Auth\AuthTrait;
use Psr\Log\LoggerInterface;
use Modules\Shared\Interfaces\UrlAggregationInterface;
use Modules\Shared\Libraries\UrlAggregation;
class ApiController extends ResourceController
{
use AuthTrait;
protected $format = "";
public object $userObject;
public UrlAggregationInterface $urlAggregation;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [
'cookie',
'url',
'from',
'filesystem',
'text',
'shared'
];
/**
* Constructor.
*
* #param RequestInterface $request
* #param ResponseInterface $response
* #param LoggerInterface $logger
*/
/**
* #var string
* Holds the session instance
*/
protected $session;
public function __construct()
{
$this->userObject = (object)[];
}
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->urlAggregation = new UrlAggregation($request);
$requestWithUser = Services::requestWithUser();
$this->userObject = $requestWithUser->getUser();
}
}
group ctl
<?php namespace Modules\Auth\Controllers;
use Modules\Auth\Config\Services;
use Modules\Auth\Entities\GroupEntity;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Shared\Controllers\ApiController;
class Group extends ApiController
{
/**
* index function
* #method : GET
*/
public function index()
{
$groupEntity = new GroupEntity();
$this->urlAggregation->dataMap($groupEntity->getDataMap());
$groupService = Services::groupService();
$findAllData = $groupService->index($this->urlAggregation);
return $this->respond([
'data' => $findAllData['data'],
'pager' => $findAllData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
/**
* show function
* #method : GET with params ID
*/
public function show($id = null)
{
$groupService = Services::groupService();
$findOneData = $groupService->show($id);
return $this->respond([
'data' => $findOneData['data'],
'pager' => $findOneData['pager']
], ResponseInterface::HTTP_OK, lang('Shared.api.receive'));
}
public function create()
{
$rules = [
'name' => 'required|min_length[3]|max_length[255]|is_unique[auth_groups.name]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->create($groupEntity);
return $this->respond([
'data' => ''
], ResponseInterface::HTTP_CREATED, lang('Shared.api.save'));
}
/**
* update function
* #method : PUT or PATCH
*/
public function update($id = null)
{
//get request from Vue Js
//get request from Vue Js
$json = $this->request->getJSON();
if (!isset($id)) {
$id = $json->id;
}
$rules = [
'name' => 'if_exist|required|min_length[3]|max_length[255]',
'description' => 'required|min_length[3]|max_length[255]',
];
if (!$this->validate($rules)) {
return $this->respond([
'error' => $this->validator->getErrors(),
], ResponseInterface::HTTP_NOT_ACCEPTABLE, lang('Shared.api.validation'));
}
$groupEntity = new GroupEntity((array)$this->request->getVar());
$groupService = Services::groupService();
$groupService->update($id, $groupEntity);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.update'));
}
/**
* edit function
* #method : DELETE with params ID
*/
public function delete($id = null)
{
$groupService = Services::groupService();
$groupService->delete($id);
return $this->respond([
], ResponseInterface::HTTP_OK, lang('Shared.api.remove'));
}
}
entitiy
<?php namespace Modules\Auth\Entities;
use \CodeIgniter\Entity;
use CodeIgniter\I18n\Time;
class GroupEntity extends Entity
{
protected $id;
protected $name;
protected $description;
//check type of data
// protected $casts = ['
// is_flag' => 'boolean'];
protected $attributes = [
'id' => null,
'name' => null,
'description' => null,
];
protected $datamap = [
];
protected $dates = [];
protected $casts = [];
protected $permissions = [];
protected $roles = [];
}
service leayer
<?php
namespace Modules\Auth\Services;
use Modules\Auth\Entities\GroupEntity;
use CodeIgniter\HTTP\ResponseInterface;
use Modules\Shared\Interfaces\UrlAggregationInterface;
use Modules\Shared\Libraries\MainService;
use Myth\Auth\Authorization\GroupModel;
class GroupService extends MainService
{
private GroupModel $model;
public function __construct()
{
$this->model = new GroupModel();
}
/**
* index function
* #method : GET
* #param UrlAggregationInterface $urlAggregation
* #return array
*/
public function index(UrlAggregationInterface $urlAggregation)
{
$pipeLine = $urlAggregation->decodeQueryParam()->getPipeLine();
return $this->model->aggregatePagination($pipeLine);
}
/**
* show function
* #method : GET with params ID
* #param $id
* #return array
*/
public function show($id)
{
if (is_null($id)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_FOUND);
$result = $this->model->where('id', $id)->paginate(1, 'default');
if (is_null($result)) $this->httpException(lang('Shared.api.exist'), ResponseInterface::HTTP_NOT_FOUND);
$data = [
'data' => $result,
'pager' => $this->model->pager->getDetails()
];
return $data;
}
/**
* create function
* #method : POST
* #param GroupEntity $entity
* #throws \ReflectionException
*/
public function create(GroupEntity $entity)
{
if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_FOUND);
if (!$this->model->save($entity)) {
helper('shared');
$this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST,serializeMessages($this->model->errors()));
}
}
/**
* update function
* #method : PUT or PATCH
* #param $id
* #param GroupEntity $entity
* #throws \ReflectionException
*/
public function update($id , GroupEntity $entity)
{
if (is_null($entity)) $this->httpException(lang('Shared.api.validation'), ResponseInterface::HTTP_NOT_FOUND);
if (!$this->model->update($id, $entity)) {
helper('shared');
$this->httpException(lang('Shared.api.reject'), ResponseInterface::HTTP_BAD_REQUEST,serializeMessages($this->model->errors()));
}
}
/**
* edit function
* #method : DELETE with params ID
* #param $id
*/
public function delete($id )
{
$deleteById = $this->model->find($id);
if (is_null($deleteById)) $this->httpException(lang('Shared.api.exist'), ResponseInterface::HTTP_NOT_FOUND);
$this->model->delete($id);
}
public function getInsertId()
{
return $this->model->getInsertID();
}
}
this is part 2
<?php namespace Modules\Auth\Config;
use CodeIgniter\HTTP\UserAgent;
use Config\App;
use Config\Services as AppServices;
use Config\Services as BaseService;
use Modules\Auth\Libraries\RequestWithUser;
use Modules\Auth\Services\AuthService;
use Modules\Auth\Services\GroupsPermissionService;
use Modules\Auth\Services\PermissionService;
use Modules\Auth\Services\RoleRouteService;
use Modules\Auth\Services\GroupService;
use Modules\Auth\Services\UsersPermissionService;
class Services extends BaseService
{
//--------------------------------------------------------------------
/**
* The Request class models an HTTP request.
*
* #param App|null $config
* #param boolean $getShared
*
* #return RequestWithUser
*/
public static function requestWithUser(App $config = null, bool $getShared = true)
{
if ($getShared) {
return static::getSharedInstance('requestWithUser', $config);
}
$config = $config ?? config('App');;
return new RequestWithUser(
$config,
AppServices::uri(),
'php://input',
new UserAgent()
);
}
//--------------------------------------------------------------------
public static function roleRoute($getShared = true)
{
if ($getShared) {
return static::getSharedInstance('roleRoute');
}
return new RoleRouteService();
}
//--------------------------------------------------------------------
public static function authService($getShared = false)
{
if (!$getShared) {
return new AuthService();
}
return static::getSharedInstance('authService');
}
//--------------------------------------------------------------------
public static function groupService($getShared = false)
{
if (!$getShared) {
return new GroupService();
}
return static::getSharedInstance('groupService');
}
//--------------------------------------------------------------------
public static function permissionService($getShared = false)
{
if (!$getShared) {
return new PermissionService();
}
return static::getSharedInstance('permissionService');
}
//--------------------------------------------------------------------
public static function groupsPermissionService($getShared = false)
{
if (!$getShared) {
return new GroupsPermissionService();
}
return static::getSharedInstance('groupsPermissionService');
}
//--------------------------------------------------------------------
public static function userPermissionService($getShared = false)
{
if (!$getShared) {
return new UsersPermissionService();
}
return static::getSharedInstance('usersPermissionService');
}
//--------------------------------------------------------------------
}
model
<?php namespace Myth\Auth\Authorization;
use CodeIgniter\Model;
use Modules\Auth\Entities\GroupEntity;
use Modules\Shared\Models\Aggregation;
class GroupModel extends Aggregation
{
protected $table = 'auth_groups';
protected $primaryKey = 'id';
protected $returnType = GroupEntity::class;
protected $allowedFields = [
'name', 'description'
];
protected $useTimestamps = false;
protected $validationRules = [
'name' => 'required|max_length[255]|is_unique[auth_groups.name,name,{name}]',
'description' => 'max_length[255]',
];
protected $validationMessages = [];
protected $skipValidation = false;
//--------------------------------------------------------------------
// Users
//--------------------------------------------------------------------
/**
* Adds a single user to a single group.
*
* #param int $userId
* #param int $groupId
*
* #return bool
*/
public function addUserToGroup(int $userId, int $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
$data = [
'user_id' => (int) $userId,
'group_id' => (int) $groupId
];
return (bool) $this->db->table('auth_groups_users')->insert($data);
}
/**
* Removes a single user from a single group.
*
* #param int $userId
* #param int|string $groupId
*
* #return bool
*/
public function removeUserFromGroup(int $userId, $groupId)
{
cache()->delete("{$groupId}_users");
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where([
'user_id' => $userId,
'group_id' => (int) $groupId
])->delete();
}
/**
* Removes a single user from all groups.
*
* #param int $userId
*
* #return bool
*/
public function removeUserFromAllGroups(int $userId)
{
cache()->delete("{$userId}_groups");
cache()->delete("{$userId}_permissions");
return $this->db->table('auth_groups_users')
->where('user_id', (int)$userId)
->delete();
}
/**
* Returns an array of all groups that a user is a member of.
*
* #param int $userId
*
* #return array
*/
public function getGroupsForUser(int $userId)
{
if (null === $found = cache("{$userId}_groups"))
{
$found = $this->builder()
->select('auth_groups_users.*, auth_groups.name, auth_groups.description')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->where('user_id', $userId)
->get()->getResultArray();
cache()->save("{$userId}_groups", $found, 300);
}
return $found;
}
/**
* Returns an array of all users that are members of a group.
*
* #param int $groupId
*
* #return array
*/
public function getUsersForGroup(int $groupId)
{
if (null === $found = cache("{$groupId}_users"))
{
$found = $this->builder()
->select('auth_groups_users.*, users.*')
->join('auth_groups_users', 'auth_groups_users.group_id = auth_groups.id', 'left')
->join('users', 'auth_groups_users.user_id = users.id', 'left')
->where('auth_groups.id', $groupId)
->get()->getResultArray();
cache()->save("{$groupId}_users", $found, 300);
}
return $found;
}
//--------------------------------------------------------------------
// Permissions
//--------------------------------------------------------------------
/**
* Gets all permissions for a group in a way that can be
* easily used to check against:
*
* [
* id => name,
* id => name
* ]
*
* #param int $groupId
*
* #return array
*/
public function getPermissionsForGroup(int $groupId): array
{
$permissionModel = model(PermissionModel::class);
$fromGroup = $permissionModel
->select('auth_permissions.*')
->join('auth_groups_permissions', 'auth_groups_permissions.permission_id = auth_permissions.id', 'inner')
->where('group_id', $groupId)
->findAll();
$found = [];
foreach ($fromGroup as $permission)
{
$found[$permission['id']] = $permission;
}
return $found;
}
/**
* Add a single permission to a single group, by IDs.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function addPermissionToGroup(int $permissionId, int $groupId)
{
$data = [
'permission_id' => (int)$permissionId,
'group_id' => (int)$groupId
];
return $this->db->table('auth_groups_permissions')->insert($data);
}
//--------------------------------------------------------------------
/**
* Removes a single permission from a single group.
*
* #param int $permissionId
* #param int $groupId
*
* #return mixed
*/
public function removePermissionFromGroup(int $permissionId, int $groupId)
{
return $this->db->table('auth_groups_permissions')
->where([
'permission_id' => $permissionId,
'group_id' => $groupId
])->delete();
}
//--------------------------------------------------------------------
/**
* Removes a single permission from all groups.
*
* #param int $permissionId
*
* #return mixed
*/
public function removePermissionFromAllGroups(int $permissionId)
{
return $this->db->table('auth_groups_permissions')
->where('permission_id', $permissionId)
->delete();
}
}
<?php
/*
* Core Auth routes file.
*/
$routes->group('api', ['namespace' => 'Modules\Auth\Controllers'], function ($routes) {
$routes->resource('group', ['filter' => 'authJwt']);
$routes->resource('permission', ['filter' => 'authJwt']);
$routes->resource('groupPermission', ['filter' => 'authJwt']);
$routes->resource('userPermission', ['filter' => 'authJwt']);
$routes->group('auth', function ($routes) {
$routes->post('signin-jwt', 'Auth::signInJwt', ['filter' => 'isSignIn']);
$routes->post('signin', 'Auth::signIn', ['filter' => 'isSignIn']);
$routes->get('signout', 'Auth::signOut', ['filter' => 'authJwt']);
$routes->get('is-signin', 'Auth::isSignIn',['filter' => 'authJwt']);
$routes->post('signup', 'Auth::signUp', ['filter' => 'isSignIn']);
$routes->post('forgot', 'Auth::forgot', ['filter' => 'isSignIn']);
$routes->post('reset-password-email', 'Auth::resetPasswordViaEmail', ['filter' => 'isSignIn']);
$routes->post('reset-password-sms', 'Auth::resetPasswordViaSms', ['filter' => 'isSignIn']);
$routes->post('activate-account-email', 'Auth::activateAccountViaEmail', ['filter' => 'isSignIn']);
$routes->post('send-activate-email', 'Auth::sendActivateCodeViaEmail', ['filter' => 'isSignIn']);
$routes->post('activate-account-sms', 'Auth::activateAccountViaSms', ['filter' => 'isSignIn']);
$routes->post('send-activate-sms', 'Auth::sendActivateCodeViaSms', ['filter' => 'isSignIn']);
});
});
I am creating a form which needs dynamic options based on the route value of survey_question_reference
'main-surveyquestions'=> [
'type' => 'segment',
'options' => [
'route' => '/survey-questions[/:survey_question_reference][/:answer]',
'constraints' => [
'survey_question_reference' => '[0-9]*',
'answer' => '(answer)',
],
'defaults' => [
'controller' => 'Main\Controller\Main',
'action' => 'surveyquestions'
]
]
],
This is the Form code which calls the FormElement:
/**
* Init
*/
public function init()
{
/**
* Survey Answer
*/
$this->add(
[
'type' => 'Main\Form\Element\SurveyAnswerRadio',
'name' => 'survey_answer',
'options' => [
'label' => 'survey_answer'
],
'attributes' => [
'id' => 'survey_answer'
]
]
);
}
The following is the code from the Form Element. Where I have hard coded 'sqReference' => '1' the 1 needs to be replaced with the value of survey_question_reference from the route.
namespace Main\Form\Element;
use Doctrine\ORM\EntityManager;
use Zend\Form\Element\Radio;
/**
* Class SurveyAnswerRadio
*
* #package Main\Form\Element
*/
class SurveyAnswerRadio extends Radio
{
/**
* #var EntityManager $entityManager
*/
protected $entityManager;
/**
* #param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
/**
* Get Value Options
*
* #return array
*
* #throws \Exception
*/
public function getValueOptions()
{
$array = [];
$result = $this->entityManager
->getRepository('AMDatabase\Entity\TheVerse\SA')
->findBy(
[
'sqReference' => '1'
],
[
'surveyAnswer' => 'ASC'
]
);
if (is_array($result) && count($result) > '0') {
/**
* #var \AMDatabase\Entity\TheVerse\SA $val
*/
foreach ($result as $val) {
$array[$val->getReference()] = $val->getSurveyAnswer();
}
}
return $array;
}
}
What you're looknig for is to inject the survey_question_reference parameter to your FormElement. You could do that as suggested by #kuldeep.kamboj in his answers. But if you don't want to change your approach and keep your custom SurveyAnswerRadio element, you have to make some fiew changes in your code :
Make SurveyAnswerRadio implements Zend\ServiceManager\ServiceLocatorAwareInterface so that you could implement setServiceLocator and getServiceLocator, which are required by the ServiceManager to automatically inject the service locator when the element is instantiated.
Your form should also implements Zend\ServiceManager\ServiceLocatorAwareInterface.
Implement the getFormElementConfig method in your Module.php.
Let’s look through the code now. You'll have something like this :
SurveyAnswerRadio :
class SurveyAnswerRadio extends Radio implements ServiceLocatorAwareInterface
{
//Add these two methods
public function setServiceLocator(ServiceLocatorInterface $sl)
{
$this->serviceLocator = $sl;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function getValueOptions()
{
$array = [];
$serviceManager = $this->serviceLocator->getServiceLocator();
$em = $serviceManager->get('Doctrine\ORM\EntityManager');
$sqReference = $serviceManager->get('application')->getMvcEvent()
->getRouteMatch()->getParam('survey_question_reference');
$result = $em->getRepository('AMDatabase\Entity\TheVerse\SA')
->findBy(
['sqReference' => $sqReference],
['surveyAnswer' => 'ASC']
);
if (is_array($result) && count($result) > '0') {
foreach ($result as $val) {
$array[$val->getReference()] = $val->getSurveyAnswer();
}
}
return $array;
}
}
Module.php :
Implement the getFormElementConfig method as follows. This allows the class ModuleName\Form\Element\SurveyAnswerRadio to be instantiated, or invoked, with the alias SurveyAnswerRadio.
class Module implements FormElementProviderInterface
{
// other stuff .....
public function getFormElementConfig()
{
return array(
'invokables' => array(
'SurveyAnswerRadio' => 'ModuleName\Form\Element\SurveyAnswerRadio'
)
);
}
}
No changes needed in the Form init method let it as it is.
Note that in your controller, you'll have to instantiate the Form via the FormElementManager :
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('ModuleName\Form\YourForm');
Please see more details in the documentation
See also this post which exaplains how to manage dependencies within a custom Select Element in Form.
I will suggest to change approach. First do not try to extends Radio Element which is not necessary at all. You can do same in your Form Class. Second your entity manager also not work in Radio/Form class until your find mechanism to pass.
So I would suggest solutions like below.
First register your form class into as factory in module.config.php
'form_elements' => array(
'factories' => array(
'Main\Form\YourFormName' => function($sm) {
$form = new Form\YourFormName();
$form->setEntityManager($sm->getServiceLocator()->get('Doctrine\ORM\EntityManager'));
$form->setServiceLocator($sm->getServiceLocator());
return $form;
},
),
),
Then implement entityManager and serviceLocator into your form class.
use DoctrineModule\Persistence\ObjectManagerAwareInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class YourFormName extends Form implements ObjectManagerAwareInterface, ServiceLocatorAwareInterface
{
protected $entityManager;
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function setEntityManager(ObjectManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function getEntityManager()
{
return $this->entityManager;
}
Then in init method you have serviceLocator/entityManager is already initialized.
public function init()
{
$routeMatch = $this->getServiceLocator()->get('Application')->getMvcEvent()->getRouteMatch();
$array = [];
$result = $this->entityManager
->getRepository('AMDatabase\Entity\TheVerse\SA')
->findBy(
[
'sqReference' => $routeMatch->getParam('survey_question_reference')
],
[
'surveyAnswer' => 'ASC'
]
);
if (is_array($result) && count($result) > '0') {
/**
* #var \AMDatabase\Entity\TheVerse\SA $val
*/
foreach ($result as $val) {
$array[$val->getReference()] = $val->getSurveyAnswer();
}
}
$this->add(
[
'type' => 'Zend\Form\Element\Radio',
'name' => 'survey_answer',
'options' => [
'label' => 'survey_answer',
'value_options' => $array,
],
'attributes' => [
'id' => 'survey_answer',
]
]
);
Following is the code which I am using for sending email but tell me How I can add attachement with this ??Following is the code which I am using for sending email but tell me How I can add attachement with this ??
<?php
namespace Application\Controller;
use Application\Filter\DomainFilter;
use Application\Form\DomainForm;
use Application\Form\SendForm;
use Application\Model\AccountModel;
use Application\Model\CustomersModel;
use Application\Model\DomainModel;
use Application\Model\UploadModel;
use Application\Service\Demo;
use Zend\Crypt\BlockCipher;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
/**
* Class DomainController
* #package Application\Controller
*/
class DomainController extends AbstractActionController
{
/**
* #var DomainModel
*/
protected $_DomainModel;
/**
* #var DomainForm
*/
protected $_DomainForm;
/**
* #var SendForm
*/
protected $_SendForm;
/**
* #var AccountModel
*/
protected $_AccountModel;
/**
* #var UploadModel
*/
protected $_UploadModel;
/**
* #var CustomersModel
*/
protected $_CustomersModel;
/**
* #var SettingModel
*/
protected $_SettingModel;
/**
* #var Demo
*/
protected $_Demo;
/**
* #param \Application\Service\Demo $Demo
*/
public function setDemo($Demo)
{
$this->_Demo = $Demo;
}
/**
* #return \Application\Service\Demo
*/
public function getDemo()
{
return $this->_Demo;
}
/**
* #param \Application\Model\CustomersModel $CustomersModel
*/
public function setCustomersModel($CustomersModel)
{
$this->_CustomersModel = $CustomersModel;
}
/**
* #return \Application\Model\CustomersModel
*/
public function getCustomersModel()
{
return $this->_CustomersModel;
}
/**
* #param \Application\Model\UploadModel $UploadModel
*/
public function setUploadModel($UploadModel)
{
$this->_UploadModel = $UploadModel;
}
/**
* #return \Application\Model\UploadModel
*/
public function getUploadModel()
{
return $this->_UploadModel;
}
/**
* #param \Application\Form\DomainForm $DomainForm
*/
public function setDomainForm($DomainForm)
{
$this->_DomainForm = $DomainForm;
}
/**
* #return \Application\Form\DomainForm
*/
public function getDomainForm()
{
return $this->_DomainForm;
}
/**
* #param \Application\Model\DomainModel $DomainModel
*/
public function setDomainModel($DomainModel)
{
$this->_DomainModel = $DomainModel;
}
/**
* #return \Application\Model\DomainModel
*/
public function getDomainModel()
{
return $this->_DomainModel;
}
/**
* #param \Application\Model\AccountModel $AccountModel
*/
public function setAccountModel($AccountModel)
{
$this->_AccountModel = $AccountModel;
}
/**
* #return \Application\Model\AccountModel
*/
public function getAccountModel()
{
return $this->_AccountModel;
}
/**
* #return the $_SendForm
*/
public function getSendForm()
{
return $this->_SendForm;
}
/**
* #param field_type $_SendForm
*/
public function setSendForm($_SendForm)
{
$this->_SendForm = $_SendForm;
}
/**
* #param mixed $SettingModel
*/
public function setSettingModel($SettingModel)
{
$this->_SettingModel = $SettingModel;
}
/**
* #return mixed
*/
public function getSettingModel()
{
return $this->_SettingModel;
}
/**
* Domain
* #return array|ViewModel
*/
public function indexAction()
{
return new ViewModel(array(
'domain' => $this->getDomainModel()->getList(),
'message' => $this->flashMessenger()->getMessages()
));
}
/**
* Add Domain
* #return \Zend\Http\Response|ViewModel
*/
public function addAction()
{
$request = $this->getRequest();
$form = $this->getDomainForm();
$form->setData(array('expired' => date('d/m/Y', strtotime('+1 year'))));
$Adapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$BC = $this->getServiceLocator()->get('block_cipher');
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => $BC['algo']));
$blockCipher->setKey($this->ApiKey()->getApiKey());
if (true === $request->isPost()) {
$post = $request->getPost()->toArray();
$form->setData($post);
$form->setInputFilter(new DomainFilter($Adapter, 0));
if (true === $form->isValid()) {
$post['created'] = date('Y-m-d H:i:s');
$post['expired'] = date('Y-m-d', $this->FormatDates()->getDateToMkTime($post['expired']));
$post['pwd_ftp'] = $blockCipher->encrypt($post['pwd_ftp']);
$this->getDomainModel()->insert($post);
$this->flashMessenger()->addMessage(array('success', 1));
return $this->redirect()->toRoute('domain');
}
}
return new ViewModel(array(
'form' => $form
));
}
/**
* Edit Domain
* #return \Zend\Http\Response|ViewModel
*/
public function editAction()
{
$ID = (int)$this->params()->fromRoute('id', 0);
$row = $this->getDomainModel()->find(array('d.id' => $ID));
$Adapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$BC = $this->getServiceLocator()->get('block_cipher');
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => $BC['algo']));
$blockCipher->setKey($this->ApiKey()->getApiKey());
if (empty($row)) {
$this->getResponse()->setStatusCode(404);
return;
}
$request = $this->getRequest();
$form = $this->getDomainForm();
$row['pwd_ftp'] = $blockCipher->decrypt($row['pwd_ftp']);
$row['expired'] = date('d/m/Y', strtotime($row['expired']));
$form->setData($row);
if (true === $request->isPost()) {
$post = $request->getPost()->toArray();
$form->setData($post);
$form->setInputFilter(new DomainFilter($Adapter, $ID));
if (true === $form->isValid()) {
$post['expired'] = date('Y-m-d', $this->FormatDates()->getDateToMkTime($post['expired']));
$post['pwd_ftp'] = $blockCipher->encrypt($post['pwd_ftp']);
$this->getDomainModel()->update($ID, $post);
$this->flashMessenger()->addMessage(array('success', 1));
return $this->redirect()->toRoute('domain');
}
}
return new ViewModel(array(
'form' => $form
));
}
/**
* Delete Domain / Account
* #return \Zend\Http\Response
*/
public function deleteAction()
{
$ID = (int)$this->params()->fromRoute('id', 0);
$this->getDomainModel()->delete($ID);
$this->getAccountModel()->deleteAllByDomain($ID);
$this->getUploadModel()->deleteAllByDomain($ID);
$this->flashMessenger()->addMessage(array('success', 1));
return $this->redirect()->toRoute('domain');
}
/**
* Detaglio Domain
* #return ViewModel
*/
public function detailAction()
{
$ID = (int)$this->params()->fromRoute('id', 0);
$domain = $this->getDomainModel()->find(array('d.id' => $ID));
if (empty($domain)) {
$this->getResponse()->setStatusCode(404);
return;
}
return new ViewModel(array(
'domain' => $domain,
'account' => $this->getAccountModel()->getList(array('a.id_domain' => $ID)),
'upload' => $this->getUploadModel()->getList(array('id_domain' => $ID)),
'type_ftp' => $this->getServiceLocator()->get('type_ftp')
));
}
/**
* Send Domain
* #return \Zend\Http\Response|ViewModel
*/
public function sendAction()
{
$ID = (int)$this->params()->fromRoute('id', 0);
$domain = $this->getDomainModel()->find(array('d.id' => $ID));
$request = $this->getRequest();
$BC = $this->getServiceLocator()->get('block_cipher');
$blockCipher = BlockCipher::factory('mcrypt', array('algo' => $BC['algo']));
$blockCipher->setKey($this->ApiKey()->getApiKey());
if (empty($domain)) {
$this->getResponse()->setStatusCode(404);
return;
}
if (true === $request->isPost()) {
$post = $request->getPost()->toArray();
$array_email = array();
if (isset($post['info_domain'])) {
$array_email['info_domain'] = array(
'fullname' => $domain['fullname'],
'url' => $domain['url'],
'auth_code' => $domain['auth_code'],
'name_provider' => $domain['name_provider'],
'name_hosting' => $domain['name_hosting'],
'name_server' => $domain['name_server']
);
}
if (isset($post['hosting_info'])) {
$pwd_ftp = !empty($domain['pwd_ftp']) ? $blockCipher->decrypt($domain['pwd_ftp']) : '';
$array_email['hosting_info'] = array(
'fullname' => $domain['fullname'],
'url' => $domain['url'],
'pwd_ftp' => $pwd_ftp,
'port_ftp' => $domain['port_ftp'],
'name_hosting' => $domain['name_hosting'],
'name_server' => $domain['name_server']
);
}
if (isset($post['ftp'])) {
$pwd_ftp = !empty($domain['pwd_ftp']) ? $blockCipher->decrypt($domain['pwd_ftp']) : '';
$array_email['ftp'] = array(
'host_ftp' => $domain['host_ftp'],
'user_ftp' => $domain['user_ftp'],
'pwd_ftp' => $pwd_ftp,
'port_ftp' => $domain['port_ftp'],
);
}
if (isset($post['email_info'])) {
$array_email['email_info'] = array(
'fullname' => $domain['fullname'],
'url' => $domain['url']
);
}
if (isset($post['account']) && is_array($post['account'])) {
$cnt = 0;
foreach ($post['account'] as $key => $value) {
$info_account = $this->getAccountModel()->find(array(
'a.id' => $value
));
$pwd = !empty($info_account['pwd']) ? $blockCipher->decrypt($info_account['pwd']) : '';
$array_email['account'][$cnt] = array(
'name_type_account' => $info_account['name_type_account'],
'usermail' => $info_account['usermail'],
'pwd' => $pwd,
'info' => $info_account['info'],
);
$cnt++;
}
}
if (isset($post['note'])) {
$array_email['note'] = $post['note'];
}
$sm = $this->getServiceLocator()->get('ServiceManager');
$translate = $sm->get('ViewHelperManager')->get('translate');
$setting = $this->getSettingModel()->find(array(
'id' => $this->WebStudioAuthentication()->getIdentity()
));
$view = new ViewModel(array(
'data' => $array_email,
));
$view->setTerminal(true);
$view->setTemplate(sprintf('Application/view/email/send_data_%s', $setting['language']));
if ($this->getDemo()->getSendEmail() === true) {
$this->mailerZF2()->send(array(
'to' => $post['email'],
'cc' => $post['usermail'],
'subject' => $translate('label_86', null, $setting['language']),
), $view);
}
$this->flashMessenger()->addMessage(array('success', 1));
return $this->redirect()->toRoute('domain/default', array('action' => 'send', 'id' => $ID));
}
return new ViewModel(array(
'demo' => $this->getDemo()->getShowMessage(),
'domain' => $domain,
'datalist' => $this->getCustomersModel()->getList(),
'form' => $this->getSendForm(),
'account' => $this->getAccountModel()->getList(array('a.id_domain' => $ID)),
'message' => $this->flashMessenger()->getMessages()
));
}
}
Here is the send form Code
<?php
namespace Application\Form;
use Zend\Form\Form;
/**
* Class SendForm
* #package Application\Form
*/
class SendForm extends Form
{
/**
* #param string $name
*/
public function __construct($name = '')
{
parent::__construct($name);
$this->setAttribute('method', 'post');
$this->setAttribute('class', 'bottom-margin');
$this->setAttribute('autocomplete', 'off');
$this->setAttribute('id', 'validateForm');
$this->add(array(
'name' => 'email',
'type' => 'Zend\Form\Element\Text',
'attributes' => array(
'class' => 'form-control',
'required' => 'required',
'list' => 'customers',
),
));
$this->add(array(
'name' => 'note',
'type' => 'Zend\Form\Element\Textarea',
'attributes' => array(
'class' => 'form-control',
)
));
}
}
getInputFilterSpecification() read twice for a fieldset when used with fileprg Controller plugin.
Basically I have a simple form with a single fieldset:
The Form:
class CreateEditReward extends ProvideEventsForm
{
public function __construct($name = null, $options = array())
{
parent::__construct($name ?: 'Reward', $options);
$this->add(array(
'name' => 'submit',
'type' => 'submit'
));
$this->add(array(
'name' => 'cancel',
'type' => 'button'
));
}
public function init()
{
parent::init();
$this->add(array(
'name' => 'reward',
'type' => 'MyAchievement\Form\RewardFieldset',
'options' => array(
'use_as_base_fieldset' => true
)
));
if (($listener = $this->get('reward')) instanceof ListenerAggregateInterface) {
/** #var $listener ListenerAggregateInterface */
$this->getEventManager()->attachAggregate($listener);
}
}
}
The form extends the most basic EventsCapable implmentation and is not related to the problem.
The Fieldset:
class RewardFieldset extends Fieldset implements
InputFilterProviderInterface,
ListenerAggregateInterface
{
/**
* #var RewardService
*/
protected $rewardService;
/**
* #var WebPathResolver
*/
protected $webPathResolver;
protected $listeners = array();
public function __construct(RewardService $rewardService, WebPathResolver $webPathResolver, $name = null, $options = array())
{
parent::__construct($name ?: 'Reward', $options);
$this->rewardService = $rewardService;
$this->webPathResolver = $webPathResolver;
//...
$this->add(array(
'name' => 'thumb',
'type' => 'file',
'options' => array(
'label' => 'Thumb'
),
'attributes' => array(
'id' => 'thumb',
'data-rel' => null
)
));
// .. more elts
}
/**
* Should return an array specification compatible with
* {#link Zend\InputFilter\Factory::createInputFilter()}.
*
* #return array
*/
public function getInputFilterSpecification()
{
return array(
// ... other elts input filters
'thumb' => array(
'required' => false,
'filters' => array(
array(
'name' => 'fileRenameUpload',
'options' => array(
'target' => './data/upload',
'overwrite' => true,
'randomize' => true,
'use_upload_name' => true
)
)
),
'validators' => array(
array(
'name' => 'fileMimeType',
'options' => array(
'image',
'enableHeaderCheck' => true
)
)
)
)
);
}
public function addThumbPreview(FormEvent $e)
{
/** #var $object Reward */
if (! ($object = $e->getObject()) instanceof Reward) {
return;
}
if ($object->getThumb()) {
$this->get('thumb')
->setAttribute('data-rel', $this->webPathResolver->getPath($object, $object->getThumb()));
}
}
/**
* Attach one or more listeners
*
* Implementors may add an optional $priority argument; the Eve\ntManager
* implementation will pass this to the aggregate.
*
* #param EventManagerInterface $events
*
* #return void
*/
public function attach(EventManagerInterface $events)
{
$this->listeners[] = $events->attach(FormEvent::EVENT_POST_BIND, array($this, 'addThumbPreview'));
}
/**
* Detach all previously attached listeners
*
* #param EventManagerInterface $events
*
* #return void
*/
public function detach(EventManagerInterface $events)
{
foreach ($this->listeners as $i => $listener) {
if ($events->detach($listener)) {
unset($this->listeners[$i]);
}
}
}
}
My controller's edit action:
public function editAction()
{
/** #var $request Request */
$request = $this->getRequest();
$back = $request->getQuery('back', $this->url()->fromRoute('admin/reward'));
/** #var $reward Reward */
if (null === $reward = $this->rewardService->fetchById($id = $this->params()->fromRoute('id'))) {
return $this->redirect()->toUrl($back);
}
$form = $this->getCreateEditForm();
$form->bind($reward);
if (($prg = $this->fileprg($form)) instanceof ResponseInterface) {
return $prg;
}
if (is_array($prg)) {
try {
if ($form->isValid()) {
$this->rewardService->updateReward($reward);
$this->flashMessenger()->addSuccessMessage('Changes saved');
$this->redirect()->toRoute('admin/reward',
array('action' => 'edit', 'id' => $id),
array('query' => array('back' => $back)));
} else {
/** #var $rewardFieldset FieldsetInterface */
$rewardFieldset = $form->get('reward');
/** #var $thumbElt ElementInterface */
$thumbElt = $rewardFieldset->get('thumb');
if (! $thumbElt->getMessages()) {
$reward->setThumb($thumbElt->getValue());
$this->rewardService->updateReward($reward);
}
}
} catch (\Exception $e) {
$this->flashMessenger()->addErrorMessage('Changes could not be saved');
return $this->redirect()->toUrl($back);
}
}
return new ViewModel(array(
'form' => $form,
'reward' => $reward,
'back' => $back
));
}
My module conf for the form:
/**
* Expected to return \Zend\ServiceManager\Config object or array to
* seed such an object.
*
* #return array|\Zend\ServiceManager\Config
*/
public function getFormElementConfig()
{
return array(
'invokables' => array(
'MyAchievement\Form\CreateEditReward' => 'MyAchievement\Form\CreateEditReward',
),
'factories' => array(
'MyAchievement\Form\RewardFieldset' => function (FormElementManager $fm) {
/** #var $rewardService RewardService */
$rewardService = $fm->getServiceLocator()->get('MyAchievement\Service\Reward');
/** #var $webPathResolver WebPathResolver */
$webPathResolver = $fm->getServiceLocator()->get('Application\Service\WebPathResolver');
$fieldset = new RewardFieldset($rewardService, $webPathResolver);
$fieldset->setHydrator(new ClassMethods());
return $fieldset;
}
)
);
}
The problem is the getInputFilterSpecifications() is called twice, thus everytime I try to upload a picture with my form I get
Zend\Filter\Exception\RuntimeException:
File './data/upload/my-thumb_5249d42bd582b.jpg' could not be renamed. An error occurred while processing the file.
That is because my filters run twice on the same thumbnail, the first time it is successful (I can even see the file uploaded to the temp dir).
Thanks.
I am using PhlyRestfully to develop a web based API that has the business logic(Services, Entities...) in other module. In order to do that I've created a module named "Api" that has configured the PhlyRestfully to use the hydrator ClassMethods. The issue is that my entity has a lot for proprieties and the api response is reflecting the entity and I don't want that.
For example my entity has the proprieties :
class Deal {
$deal_id;
$title;
$description;
$price;
}
The fetch method created in Model/Service is returning a Deal but it selects only the title and deal_id because these are only columns that I want to display in the response. The response doesn't have only the title and deal_id as I wanted but is reflecting the hole entity. If I'm not specifying the hydrator in the config the response is how I wanted (wih title and deal_id) but there is another problem in response, the key has an additional text("\u0000*\u0000).From what I saw in the code the additional text is added because of the cast and a hydrator is necessary.
There is any solution to resolve this problem without build a separate logic in the "Api" module? Can someone suggest me any other solutions ?
Resource:
namespace Api\Resources;
class Deals extends AbstractListenerAggregate
{
protected $listeners = array();
protected $table;
public function __construct($table)
{
$this->table = $table;
}
public function attach(EventManagerInterface $events)
{
$this->listeners[] = $events->attach('create', array($this, 'onCreate'));
$this->listeners[] = $events->attach('fetch', array($this, 'onFetch'));
$this->listeners[] = $events->attach('fetchAll', array($this, 'onFetchAll'));
}
public function onCreate(ResourceEvent $e)
{
$data = $e->getParam('data');
$paste = $this->table->save($data);
if (!$paste) {
throw new CreationException();
}
return $paste;
}
public function onFetch(ResourceEvent $e)
{
$id = $e->getParam('id');
$paste = $this->table->getDealMapper()->fetchById($id);
$paste->addresses = new HalResource(array('deals'), 1);
if (!$paste) {
throw new DomainException('Paste not found', 404);
}
return $paste;
}
public function onFetchAll(ResourceEvent $e)
{
// getDealsApi is selecting only the deal_id and the title
$deals = $this->table->getDealMapper()->getDealsApi();
foreach($deals as $deal) {
$deal->categories = array(
'3' => array(
'name' => 'asdasd',
'href' => 'url'
)
);
}
return $deals;
}
}
Entity from the "Common" module:
namespace Common\Entity;
class Deal
{
protected $deal_id;
protected $store_id;
protected $title;
protected $short_description;
protected $list_price;
protected $price;
protected $discount;
protected $discount_type;
protected $image_url;
protected $link;
/**
* #return dealId
*/
public function getDealId()
{
return $this->deal_id;
}
/**
* #param $dealId
* #return self
*/
public function setDealId($dealId)
{
$this->deal_id = (int) $dealId;
return $this;
}
/**
* #return store_id
*/
public function getStoreId()
{
return $this->store_id;
}
/**
* #param $storeId
* #return self
*/
public function setStoreId($storeId)
{
$this->store_id = $storeId;
return $this;
}
/**
* #return title
*/
public function getTitle()
{
return $this->title;
}
/**
* #param $title
* #return self
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* #return shortDescription
*/
public function getShortDescription()
{
return $this->short_description;
}
/**
* #param $description
* #return self
*/
public function setShortDescription($description)
{
$this->short_description = $description;
return $this;
}
/**
* #return link
*/
public function getLink()
{
return $this->link;
}
/**
* #param $link
* #return self
*/
public function setLink($link)
{
$this->link = $link;
return $this;
}
/**
* #return list_price
*/
public function getListPrice()
{
return $this->list_price;
}
/**
* #param $listPrice
* #return self
*/
public function setListPrice($listPrice)
{
$this->list_price = $listPrice;
return $this;
}
/**
* #return price
*/
public function getPrice()
{
return $this->price;
}
/**
* #param $price
* #return self
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* #return discount
*/
public function getDiscount()
{
return $this->discount;
}
/**
* #param $discount
* #return self
*/
public function setDiscount($discount)
{
$this->discount = $discount;
return $this;
}
/**
* #return discount_type
*/
public function getDiscountType()
{
return $this->discount_type;
}
/**
* #param $discounType
* #return self
*/
public function setDiscountType($discounType)
{
$this->discount_type = $discounType;
return $this;
}
/**
* #return image_url
*/
public function getImageUrl()
{
return $this->image_url;
}
/**
* #param $imageUrl
* #return self
*/
public function setImageUrl($imageUrl)
{
$this->image_url = $imageUrl;
return $this;
}
}
Api module config:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Api\Controller\Index' => 'Api\Controller\IndexController',
),
),
'router' => array(
'routes' => array(
'api' => array(
'type' => 'Literal',
'options' => array(
'route' => '/api',
'defaults' => array(
'__NAMESPACE__' => 'Api\Controller',
'controller' => 'Index',
// 'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'deals' => array(
'type' => 'Segment',
'options' => array(
'route' => '/deals[/[:id]]',
// 'controller' => 'Api\Controller\Deals',
'defaults' => array(
'controller' => 'Api\Controller\Deals',
),
),
),
),
),
),
),
'view_manager' => array(
'strategies' => array(
'ViewJsonStrategy'
),
),
'phlyrestfully' => array(
'resources' => array(
'Api\Controller\Deals' => array(
'listener' => 'Api\Resource\Deal',
'route_name' => 'api/deals',
'resource_http_options' => array('get'),
'page_size' => 1,
)
),
'renderer' => array(
'hydrators' => array(
'Common\Entity\Deal' =>'Hydrator\ClassMethods',
),
),
),
'service_manager' => array(
'invokables' => array(
'Hydrator\ClassMethods' => 'Zend\Stdlib\Hydrator\ClassMethods',
),
),
);
The response using this code :
{
"_links": {
"self": {
"href": "http://deal.local.com/api/deals?page=1"
},
"first": {
"href": "http://deal.local.com/api/deals"
},
"last": {
"href": "http://deal.local.com/api/deals?page=1"
}
},
"_embedded": {
"items": [
{
"deal_id": 1,
"type": null,
"store_id": null,
"title": "Title of the deal",
"short_description": null,
"long_description": null,
"status": null,
"slug": null,
"link": null,
"list_price": null,
"price": null,
"discount": null,
"discount_type": null,
"image_url": null,
}
]
}
}
From what you can see it sets NULL for the keys that are not returned by the getDealsApi()
And I want to look like this:
{
"_links": {
"self": {
"href": "http://deal.local.com/api/deals?page=1"
},
"first": {
"href": "http://deal.local.com/api/deals"
},
"last": {
"href": "http://deal.local.com/api/deals?page=1"
}
},
"_embedded": {
"items": [
{
"deal_id": 1,
"title": "Title of the deal",
}
]
}
}
Any help will be very appreciated!
Thank you
I think you should do like this:
$deals = $this->table->getDealMapper()->getDealsApi();
$a = array();
foreach($deals as $deal) {
$deal->categories = array(
'3' => array(
'name' => 'asdasd',
'href' => 'url'
)
);
$a[] = $deal;
}
$deals = $a