ZF2 with PhlyRestfully the json response is reflecting the entity structure - php

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

Related

RestFul API For Delete And Update Get 403 Forbidden Codeigniter 4

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']);
});
});

How to get session data and put in a dropDownList in Yii 2?

I'm new in StackOverflow and also new using the framework Yii 2, and I need to get session data and put in a create and update form using the _form.php from a view called Planficacion, but when I try to use this line of code in the form:
<?= $form->field($model, 'rutProfesor')->dropDownList(ArrayHelper::getvalue(Yii::$app->user->identity->rutProfesor,'nombreProfesor')) ?>
Return this error: PHP Warning – yii\base\ErrorException. Invalid argument supplied for foreach()
I need to get the value of 'nombreProfesor' from a model called Profesor, and the relation of both Planificacion and Profesor is 'rutProfesor' and I want to show in the dropDownList only the 'nombreProfesor' of the actual session.
There are the codes from:
Profesor Model (Profesor.php)
<?php
namespace common\models;
use Yii;
class Profesor extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'profesor';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['rutProfesor'], 'required'],
[['nombreProfesor', 'apellidoProfesor', 'escuelaProfesor'], 'string', 'max' => 45],
[['rutProfesor', 'claveProfesor'], 'string', 'max' => 15],
[['rol'], 'string', 'max' => 2],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'nombreProfesor' => 'Nombre Profesor',
'apellidoProfesor' => 'Apellido Profesor',
'escuelaProfesor' => 'Escuela',
'rutProfesor' => 'Rut',
'claveProfesor' => 'Clave Profesor',
'rol' => 'Rol',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getPlanificacions()
{
return $this->hasMany(Planificacion::className(), ['rutProfesor' => 'rutProfesor']);
}
}
Planificacion Model (planificacion.php)
<?php
namespace common\models;
use Yii;
class Planificacion extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'planificacion';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['fecha', 'fechaRevision', 'fechaPlanificacion'], 'safe'],
[['objetivosPlanificacion', 'actividad1', 'actividad2', 'actividad3', 'actividad4', 'obsActividad1', 'obsActividad2', 'obsActividad3', 'obsActividad4', 'contenidoActividad1', 'contenidoActividad2', 'contenidoActividad3', 'contenidoActividad4'], 'string'],
[['rutProfesor'], 'string', 'max' => 15],
[['nombreSesion', 'recursosUtilizadosPlanificacion', 'estadoActividad1', 'estadoActividad2', 'estadoActividad3', 'estadoActividad4', 'evalActividad1', 'evalActividad2', 'evalActividad3', 'evalActividad4', 'nombreSupervisor', 'asistencia'], 'string', 'max' => 255],
[['estado', 'rutSupervisor'], 'string', 'max' => 30],
[['rutProfesor'], 'exist', 'skipOnError' => true, 'targetClass' => Profesor::className(), 'targetAttribute' => ['rutProfesor' => 'rutProfesor']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'idPlanificacion' => 'Id Planificacion',
'rutProfesor' => 'Nombre Profesor',
'fecha' => 'Fecha',
'nombreSesion' => 'Nombre Sesion',
'objetivosPlanificacion' => 'Objetivos Planificacion',
'recursosUtilizadosPlanificacion' => 'Recursos Utilizados Planificacion',
'actividad1' => 'Actividad1',
'actividad2' => 'Actividad2',
'actividad3' => 'Actividad3',
'actividad4' => 'Actividad4',
'estadoActividad1' => 'Estado Actividad1',
'estadoActividad2' => 'Estado Actividad2',
'estadoActividad3' => 'Estado Actividad3',
'estadoActividad4' => 'Estado Actividad4',
'obsActividad1' => 'Obs Actividad1',
'obsActividad2' => 'Obs Actividad2',
'obsActividad3' => 'Obs Actividad3',
'obsActividad4' => 'Obs Actividad4',
'contenidoActividad1' => 'Contenido Actividad1',
'contenidoActividad2' => 'Contenido Actividad2',
'contenidoActividad3' => 'Contenido Actividad3',
'contenidoActividad4' => 'Contenido Actividad4',
'evalActividad1' => 'Eval Actividad1',
'evalActividad2' => 'Eval Actividad2',
'evalActividad3' => 'Eval Actividad3',
'evalActividad4' => 'Eval Actividad4',
'estado' => 'Estado',
'fechaRevision' => 'Fecha Revision',
'rutSupervisor' => 'Rut Supervisor',
'fechaPlanificacion' => 'Fecha Planificacion',
'nombreSupervisor' => 'Nombre Supervisor',
'asistencia' => 'Asistencia',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getAsistencias()
{
return $this->hasMany(Asistencia::className(), ['idPlanificacion' => 'idPlanificacion']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getRutProfesor0()
{
return $this->hasOne(Profesor::className(), ['rutProfesor' => 'rutProfesor']);
}
}
User Model (User.php)
<?php
namespace common\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\helpers\Security;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
const ROLE_SUPERVISOR = 1;
const ROL_PROFESOR = 2;
public $authKey;
/** #inheritdoc
/**
*/
public static function tableName()
{
return 'profesor';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
];
}
/**
* #inheritdoc
*/
public static function findIdentity($rutProfesor)
{
return static::findOne(['rutProfesor' => $rutProfesor]);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($rutProfesor)
{
return static::findOne(['rutProfesor' => $rutProfesor]);
}
/**
* Finds user by password reset token
*
* #param string $token password reset token
* #return static|null
*/
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token,
'status' => self::STATUS_ACTIVE,
]);
}
/**
* Finds out if password reset token is valid
*
* #param string $token password reset token
* #return bool
*/
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$timestamp = (int) substr($token, strrpos($token, '_') + 1);
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
return $timestamp + $expire >= time();
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return bool if password provided is valid for current user
*/
public function validatePassword($claveProfesor)
{
return $this->claveProfesor === $claveProfesor;
}
/**
* Generates password hash from password and sets it to the model
*
* #param string $password
*/
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
/**
* Generates "remember me" authentication key
*/
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
public function isUserSimple($rutProfesor)
{
if(static::findOne(['rutProfesor' => $rutProfesor, 'rol' => 2]))
{
return true;
} else {
return false;
}
}
public function isUserAdmin($rutProfesor)
{
if(static::findOne(['rutProfesor' => $rutProfesor, 'rol' => 1]))
{
return true;
} else {
return false;
}
}
}
Planificacion Controller (planificacionController.php)
<?php
namespace frontend\controllers;
use Yii;
use common\models\Planificacion;
use common\models\PlanificacionSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* PlanificacionController implements the CRUD actions for Planificacion model.
*/
class PlanificacionController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Planificacion models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new PlanificacionSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Planificacion model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Planificacion model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Planificacion();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->idPlanificacion]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Planificacion model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->idPlanificacion]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Planificacion model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Planificacion model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Planificacion the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Planificacion::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
First, why you getting the error, is because ArrayHelper::getValue() require an array as first parameter, as it's purpose is to
Retrieves the value of an array element or object property with the
given key or property name.
And Yii::$app->user->identity->rutProfesor wouldn't yield an array, no, it would yield an single string, which is current rutProfessor in the session.
Then, on how you create the dropDownList you wanted, i suggest using an ArrayHelper::map() which is more straightfoward.
<?= $form->field($model, 'rutProfesor')->dropDownList(ArrayHelper::map(Profesor::find()->where([
'rutProfesor' => Yii::$app->user->identity->rutProfesor
])->all(), 'rutProfesor', 'nombreProfesor'); ?>
I beleive that code will do you good.
Happy coding. :)

Custom validator not found by ValidatorPluginManager

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.

I want to Add attachment on ZendF2 Email but I cant understand what I do with following code?

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',
)
));
}
}

ZF2: FieldSet getInputFilterSpecification() gets called twice

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.

Categories