Sending arguments to a PHP callback - php

I'm using wordpress wp-api to create some endpoints and I have this call:
register_rest_route('1.00', '/trial/confirm', array(
'methods' => 'POST',
'callback' => array($trial_service, 'callback_confirm'),
'permission_callback' => array($this, 'check_permission_master'),
'args' => array(
'token' => array(
'required' => true,
'sanitize_callback' => 'esc_attr'
)
)
));
I would like to know how to pass arguments beyond just $request to the permission_callback function. Any help would be much appreciated.

You can not send more arguments to that function, but you can create a class which holds the method check_permission_master. Then pass all arguments that you need to that class (for example on construct). And later use them inside check_permission_master. For example:
class Permissions
{
protected $param1;
protected $param2;
public function __construct($param1, $param2)
{
$this->param1 = $param1;
$this->param2 = $param2;
}
public function check_permission_master($request)
{
...
}
}
And then use it in your code:
$permissions = new Permissions(...);
...
'permission_callback' => array($permissions, 'check_permission_master'),
...

Related

passing variable from php function to another inside class - PHPUnit

after creating inside setUp() two variables, i cant figure out how should i pass them to second function and use them.
this is my last attempt:
class adRequestTest extends PHPUnit_Framework_TestCase{
protected function setUp(){
$env = \Slim\Environment::mock([
'REQUEST_METHOD' => 'PUT',
'REQUEST_URI' => '/foo/bar',
'QUERY_STRING' => 'abc=123&foo=bar',
'SERVER_NAME' => 'example.com',
'CONTENT_TYPE' => 'application/json;charset=utf8',
'CONTENT_LENGTH' => 15
]);
$request = new \Slim\Http\Request($env);
}
function testInitFromHttpRequest_correctConstruction($request, $env){
$fixture = new AdRequest();
$fixture->initFromHttpRequest($request, $env);
}
}
i tried doing that by passing them like this as well :
function testInitFromHttpRequest_correctConstruction($request = $this->request, $env = $this->env)
but didnt work as well.
i am getting this error:
Missing argument 1 for adRequestTest::testInitFromHttpRequest_correctConstruction()
but i am passing two arguments like defined in the declaration... what am i missing here?? thx
The PHPunit framework don't pass any arguments to your function until you don't define a dataprovider (is not your case/scenario).
You can try this modified test case that define as class scope the variable you define in the setup method:
class adRequestTest extends PHPUnit_Framework_TestCase{
private $env;
private $request;
protected function setUp(){
$this->env = \Slim\Environment::mock([
'REQUEST_METHOD' => 'PUT',
'REQUEST_URI' => '/foo/bar',
'QUERY_STRING' => 'abc=123&foo=bar',
'SERVER_NAME' => 'example.com',
'CONTENT_TYPE' => 'application/json;charset=utf8',
'CONTENT_LENGTH' => 15
]);
$this->request = new \Slim\Http\Request($this->env);
}
function testInitFromHttpRequest_correctConstruction(){
$fixture = new AdRequest();
$fixture->initFromHttpRequest($this->request, $this->env);
// write here your tests/assertions...
}
}
Hope this help

Phalcon php pass parameter in constructor

I would like to pass parameter to constructor in controller. Is it possible to do ?
I am trying to pass interface defination in constructor.
or is it possible to bind or set constructor in DI ?
below is my code.
<?php
use Phalcon\Repositories\IUsersRepository;
class UsersController extends ControllerBase
{
private $users;
public function __construct(IUsersRepository $usersRepository)
{
$this->users = $usersRepository;
}
?>
I have fixed by using below code in service.php
$di->set('usersRepository', array(
'className' => 'Phalcon\Repositories\UsersRepository'
));
$di->set('UsersController', array(
'className' => 'UsersController',
'arguments' => array(
array('type' => 'service', 'name' => 'usersRepository')
)
));
Yes you can.. take a look...
http://docs.phalconphp.com/en/latest/reference/di.html#instantiating-classes-via-the-service-container
If you want to send data on every request use dispatch Service
$di->set('IndexController', function() {
$component = new Component();
$component->private_method();
return $component;
}, true);
I wonder y u need this method!

PHP magic method __invoke, empty instance variables

I'm facing a problem when calling __invoke() on an object. Is __invoke() method agnostic to instance variables? I need to call __invoke() directly on my templates due to some ZF2 injection to call $this->getView()->render(...) (otherwise getView() returns null) and I would like to have instance variables setted there. Any workaround?
See my code:
namespace Person\Person\View\Helper;
use Zend\View\Helper\AbstractHelper;
class PersonShowWidget extends AbstractHelper
{
protected $model = null;
public function __construct(array $options = null)
{
$this->parseOptions($options);
}
public function __invoke()
{
var_dump($this->model); //returns null
return $this->getView()->render('person/show/show_widget', array(
'title' => 'Cliente',
'model' => $this->model,
)
);
}
public function setOptions(array $options = null)
{
$this->parseOptions($options);
}
protected function parseOptions(array $options = null)
{
if (!is_null($options) && is_array($options)) {
if (isset($options['model'])) {
$model = $options['model'];
if (isset($model['id'])) {
$this->model['id'] = $model['id'];
} else {
throw new \Exception;
}
if (isset($model['form'])) {
$this->model['form'] = $model['form'];
} else {
throw new \Exception;
}
}
}
var_dump($this->model); //returns valid data
}
}
I do have called the constructor with some options or the setOptions method before calling __invoke().
Thanks,
You have to initialize the view helper with a factory. In this way you can make sure the constructor is called before the __invoke method is called. And no..the __invoke() method is not agnostic to instance variables.
In the Module.php
public function getViewHelperConfig()
{
return array(
'factories' => array(
'personShowWidget' => function ($helpers) {
$array = array();
$helper = new Person\Person\View\Helper\PersonShowWidget($array);
return $helper;
},
)
);
}
Or in the module.config.php
'view_helpers' => array
(
'factories' => array(
'personShowWidget' => function ($helpers) {
$array = array();
$helper = new Person\Person\View\Helper\PersonShowWidget($array);
return $helper;
},
)
)
Performance-wise you'd better make a Factory class instead of a callable.
More info: http://framework.zend.com/manual/2.0/en/modules/zend.module-manager.module-manager.html
Edit:
It seems like you using the ViewHelper wrongly. You don't have to create the instance by yourself. Just use the ViewHelper in the view. So why not just give the $options as parameter to the __invoke method?
public function __invoke(array $options = null)
{
$this->setOptions($options);
return $this->getView()->render('person/show/show_widget', array(
'title' => 'Cliente',
'model' => $this->model,
)
);
}
In the Controller pass the options array to the view:
return array(
'options' => $options,
);
And call the ViewHelper in the view:
<?php echo $this->personShowWidget($this->options); ?>
Remember: In this way you don't need a Factory to init the ViewHelper. Just add it to the invokables.
module.config.php example:
'view_helpers' => array(
'invokables' => array(
'personShowWidget' => 'Person\Person\View\Helper\PersonShowWidget',
),
),

zf2 Trying to inject input filter into service

I'm attempting to create a custom filter and inject it into a service via factory.
use Zend\InputFilter\InputFilter;
class WSRequestFilter extends InputFilter{
protected $inputFilter;
public function init(){
$this->add( array(
'name' => 'apiVersion',
'required' => true,
'filters' => [
array('name' => 'Real'),
...
In Module.php...
public function getServiceConfig(){
return array(
...
'factories' => array(
'Puma\Service\WebServiceLayer' => function($sm) {
$wsRequestFilter = new Filter\WSRequestFilter();
$wsRequestFilter->init();
$wsl = new Service\WebServiceLayer($wsRequestFilter);
return $wsl;
},
),
);
}
But I get service not found exception when executing $wsRequestFilter->init();. I have also tried to initialize the filter using the InputFilterManager similar to here but I got a service not found trying to access the manager via $serviceManager->get('InputFilterManager'). I think I am missing something fundamental here.
The init() method invoked automatically by InputFilterManager just after the filter object created. You don't need to invoke manually.
Add this to your module configuration:
'input_filters' => array(
'invokables' => array(
'ws-request-filter' => '\YourModule\Filter\WSRequestFilter',
),
),
And change your service factory like below:
public function getServiceConfig(){
return array(
...
'factories' => array(
'Puma\Service\WebServiceLayer' => function($sm) {
$filter = $sm->get('InputfilterManager')->get('ws-request-filter')
$wsl = new \YourModule\Service\WebServiceLayer($filter);
return $wsl;
},
),
);
}
It should work.

Upsert embedded document in yiimongodbsuite

I need to perform an upsert command in yiimongodbsuite.
I tried
$model = new Murls();
$model->userid=$userid;
$model->title=$title;
$model->edits[0] = new Medithtml();
$model->edits[0]->path= $htm;
$model->edits[0]->html=$path;
$model->edits[0]->ci=$ci;
$model->update(array('_id'=>$rec->_id ),array('userid', 'title','edits' ), true );
But this shows an error.
Murls model is defined as follows
class Murls extends EMongoDocument
{
public $userid;
public $title;
public $edits;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
// This method is required!
public function getCollectionName()
{
return 'murls';
}
public function attributeLabels()
{
return array(
'html'=>'Html',
);
}
public function embeddedDocuments()
{
return array(
// property name => embedded document class name
'edits'=>'Medithtml',
);
}
public function behaviors(){
return array(
'embeddedArrays' => array(
'class' => 'ext.YiiMongoDbSuite.extra.EEmbeddedArraysBehavior',
'arrayPropertyName' => 'edits', // name of property, that will be used as an array
'arrayDocClassName' => 'Medithtml' // class name of embedded documents in array
),
);
}
}
and model Medithtml as
class Medithtml extends EMongoEmbeddedDocument{
public $html;
public $path;
public $ci;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
What I need to achieve is that a record with $title can have n number of $html , $path and $ci.
Any help will be appreciated.
What I am looking is to store data like this
array (
'_id' =>
MongoId::__set_state(array(
'$id' => '51ee1956d39c2c7e078d80da',
)),
'userid' => '12',
'title' => 'Mongo',
'edits' =>
array (
0 =>
array (
'html' => 'html>body>div:nth-child(2)>a>div>a>div',
'path' => 'ssssss',
'ci' => '1',
),
1 =>
array (
'html' => 'html>body>div:nth-child(2)>a>div:nth-child(3)>a>h2',
'path' => '/assets/img/demo/demo-avatar9604.jpg',
'ci' => '2',
),
2 =>
array (
'html' => ' html>body>div:nth-child(2)>a>div:nth-child(3)>a>center:nth-child(16)>a>h1',
'path' => '333',
'ci' => '3',
),
),
)
Only the comments array will be updated if record with a particular combination of 'title' and 'userid' exists.If it doesn not exists a new record will be inserted
You are inheriting from wrong class. To save document you must inherit from EMongoDocument not EMongoEmbeddedDocument. These classes are similar but have different purpose.
EMongoEmbeddedDocument Is for embedded documents only, it should be used only for embedded documents
EMongoDocument extends from EMongoEmbeddedDocument with methods to actually save data to db.
For array of comments, you have two options:
Use plain php array - simple less maintanable, less power, erron prone..
Use array of embedded documents - each comment is document, so can be validated, has rigid structure etc.
By default save/insert/update stores all attributes. For partial updates use combination of $attributes and set $modify to true. Warning: Passing array of attributes without $modify will store only passed attributes, discarding rest of document.
public function save($runValidation = true, $attributes = null)
...
public function insert(array $attributes = null)
...
public function update(array $attributes = null, $modify = false)
...
So in your case you can update like that:
$model->update(array('comments'), true);
Or if it's ok for you to ovverride whole document just save:
$model->save();
Note: for composite pk ovverride primaryKey():
public function primaryKey()
{
return array('title', 'userid');
}
Uh, good that stackoverflow have drafts autosave feature:)
Finally I got solution in this way:
$rec = $model->find($criteria) ;
if($rec){
foreach($rec->edits as $editarray){
$var[]=$editarray;
}
$edits_new= new Medithtml();
$edits_new['html']=$htm;
$edits_new['ci']=$ci;
$edits_new['path']=$path;
$var[]=$edits_new;
$rec->edits=$var;
$rec->userid=$userid;
$rec->title=$title;
$rec->update(array('edits' ), true);
}

Categories