backpack for laravel: how to add a custom action / operation? - laravel-backpack

I need to add and operation to handle downloading of a file.
How can i create route, and add setupDownloadOperation in the right way?
Or must I simply do 'laravel-way' manually adding a route?

Actually we did this
First - Create a setupDownloadRoutes
Actually this is called automatically ad boot
protected function setupDownloadRoutes($segment, $routeName, $controller)
{
Route::get($segment. '/{id}/download', [
'as' => $routeName . '.download',
'uses' => $controller . '#download',
'operation' => 'download',
]);
}
Create the setupDownloadOperation function
It's automatically launched if found. If you have nothing to do here you can avoid to create it.
protected function setupDownloadOperation()
{
...do things here...
}
Create the download function.
This is the classic controller action of Laravel
protected function download()
{
... do thing as usually in a normal action ...
}
I do not find these procedure documented actually

The docs here cover exactly what you need. Just replace “moderate” with “download” in the naming - https://backpackforlaravel.com/docs/4.1/crud-operations

Related

use softDelete in backpack and deactive in operations

I use backpack and laravel and I want to see deleted item in show for example...
but because soft delete active a global scope I can't see the deleted item.
I don't know how to deactive scope in some operation for example in show operation that backpack use it for showing an element...
I hope you help me...
I'm using backpack-revision and when I want to see the revisions for a soft deleted item I have that problem too.
To show them inside the list operation I usually add a filter like this in my setupListOperation():
$this->crud->addFilter(
[
'type' => 'simple',
'name' => 'trashed',
'label'=> 'Trashed',
],
false,
function ($values) {
// if the filter is active
$this->crud->query = $this->crud->query->onlyTrashed();
}
);
To show them in other operations it should be possible to something like:
public function setupShowOperation()
{
$this->crud->query = $this->crud->query->withTrashed();
}
In Backpack 5, this was the solution for me:
protected function setupShowOperation()
{
$this->setupListOperation();
$this->crud->set('show.softDeletes', true);
}
This is an undocumented feature, but I found this in the show() method of the ShowOperation trait.

How to call custom filters in Zend?

I want to use htmlpurifier on my website, but can't figure out how to load my filter in the view. I've added my filter the way described in the first answer here.
I want to be able to call it from my view with something like $this->filter($content) Any suggestions how I do that?
It is a two step process:
Write an actual Zend_Filter implementation of HTMLPurifier (done, answer in the question you mentioned)
Write a view helper
It will look like this:
class My_View_Helper_Purify extends Zend_View_Helper_Abstract
{
public function purify($value)
{
$filter = new My_Filter_HtmlPurifier();
return $filter->filter($value);
}
}
Don't forget to add your custom view helper path:
$view->addHelperPath(
APPLICATION_PATH . '/../library/My/View/Helper',
'My_View_Helper_'
);
And later in any of your view scripts:
<?= $this->purify($text) ?>

How do I change the tag used by Zend_View_Helpers_FormErrors?

When using Zend_Form, if an element is not valid the form returns the errors by way of an unordered list. How do I change this to use paragraph tags instead?
I have attempted loading the Errors decorator for the elements and calling setOptions() to pass in a bunch of tags to replace the ul/li stuff being used by Zend_Form_Decorator_FormErrors, but that didn't work =/ Instead Zend_Form_Decorator_Errors just put the options as attribute/value pairs in the ul tag.
Instead of extending the Errors decorator I have extended the formErrors view helper, getting it to accept and process the options in the array. The formErrors view helper has setters to let me change the tags being used:
class My_View_Helper_FormErrors extends Zend_View_Helper_FormErrors
{
public function formErrors($errors, array $options = null)
{
if(key_exists('htmlElementStart', $options))
{
$this->setElementStart($options['htmlElementStart']);
unset($options['htmlElementStart']);
}
if(key_exists('htmlElementEnd', $options))
{
$this->setElementEnd($options['htmlElementEnd']);
unset($options['htmlElementEnd']);
}
if(key_exists('htmlElementSeparator', $options))
{
$this->setElementSeparator($options['htmlElementSeparator']);
unset($options['htmlElementSeparator']);
}
return parent::formErrors($errors, $options);
}
}
To pass options, I got the error decorator and setOptions() on it:
$element->getDecorator()->setOptions(
array(
'class' => 'error',
'htmlElementStart' => '<p%s>',
'htmlElementEnd' => '</p>',
'htmlElementSeparator' => '<br/>'
)
);
And tell the elements to load the helper path:
$element->getView()->addHelperPath('My/View/Helper', 'My_View_Helper');
Unfortunatelly, you cannot change the output format by just passing a bunch of options.
If you like to change this behaviour you have no choice but to write your own Errors decorator (most likely a derivative from the original Errors decorator). This new decorator has to have its render () method overwritten in order to be able to call your own view helper (instead of the formErrors helper which ZF uses by default).

Wordpress: Accessing A Plugin's Function From A Theme

I'm trying to add some functionality from a plugin I have made into a Wordpress theme but I am having little joy. The documentation doesn't really help me solve the problem so perhaps someone here can help.
I have a plugin in Wordpress that is activated and working fine. The class for this plugin has a function called generateHtml which I would like to access from a Wordpress Theme. But whatever I try, I cannot seem to access my plugin's code.
Can either give me a summary of what I need to do to get a theme accessing code from a plugin and/or point out there I am going wrong in my code:
Plugin:
<?php
/** Usual comments here **/
if (!class_exists("ImageRotator")) {
class ImageRotator {
private $uploadPath = '';
private $pluginPath = '';
private $options;
function __construct() {
$this->uploadPath = dirname(__file__).'\\uploads\\';
// add_shortcode('imagerotator', array(&$this, 'generateHtml'));
}
// Various functions for plugin
function generateHtml() {
echo '<p>Hello World</p>';
}
}
}
/**
* Create instance of image rotator
*/
$imageRotator = new ImageRotator();
/**
* Create actions & filters for Wordpress
*/
if (isset($imageRotator)) {
// Actions
add_action('admin_menu', array(&$imageRotator, 'createMenu'));
add_action('admin_init', array(&$imageRotator, 'registerSettings'));
add_action('imagerotator_show', array(&$imageRotator, 'generateHtml'));
}
Portion from theme header page:
<?php if (isset($imageRotator)) {
$imageRotator->generateHtml();
} else if (isset($ImageRotator)) {
print_r($ImageRotator);
} else {
echo '<p>Nope!</p>';
}
if (function_exists("imagerotator_show")) {
echo 'Function found';
} else {
echo 'Function NOT found';
}
?>
Currently all I ever see is "Nope" and "Function NOT found". Thanks for any input.
Lee,
For starters, "imagerotator_show" is not a function; it's the name of a type of action. When you use the add_action() function, Wordpress just adds your method to the list of functions/methods to call when a particular action is triggered. Thus your second test will always respond with 'Function NOT found'.
The most likely cause of the first problem is failing to declare the method you want to call as a public method. You're also making the code harder than it needs to be.
The best practice I've seen for declaring methods and registering hooks from a class looks something like this:
if ( ! class_exists( 'Foo' ) ):
class Foo {
function __construct() {
add_action( 'hook_name', array( &$this, 'my_hook_implementation' ) );
}
function my_hook_implementation() {
// does something
}
public function my_special_method() {
// does something else
}
}
if ( class_exists( 'Foo' ) ):
$MyFoo = new Foo();
This allows your class to keep all of its implementation details private. When you need to call my_special_method(), you do it as follows:
$MyFoo->my_special_method();
#andrew since I can't comment I thought I would answer your ancillary question. See:
http://net.tutsplus.com/tutorials/wordpress/create-wordpress-plugins-with-oop-techniques/
Where it is explained that when defining a callback function from an object you have to use the array function. It's basically saying get the function 'my_hook_implementation' from the object $this and use it as the callback parameter to the add action hook. It is because you defined the function within the scope of the object and you have to define the scope in order for PHP to know what function you are talking about. The scope being the object referred to by the variable $this.
You just need to use do_action() function, inside your theme.
If you want the function generateHtml to appears inside your header.php you just need to open the header.php file and paste <?php do_action('imagerotator_show'); ?> where you want and then your function will be called there.

How do you Unit Test a Zend_Form that includes the CSRF form element?

I'm using the CSRF hidden hash element with Zend_Form and trying to Unit Test the login but don't know how to write a Unit Test to include that element. Looked in the docs and read as many tutorials as I could find. I even delicioused them all, but no one mentions this.
Csrf value is generated each time form is rendered. Hidden element of the form gets prefilled with that value. This value also gets stored in session.
After submitting form, validation checks if value posted from the form is stored in session, if not then validation fails. It is essential, that form must be rendered during the test (so it can generate the hidden value and store it to session), then we can extract what is the hidden value out of rendered html, and later we can add hidden hash value into our request.
Consider this example:
function testAddPageStoreValidData()
{
// render the page with form
$this->dispatch('/form-page');
// fetch content of the page
$html = $this->getResponse()->getBody();
// parse page content, find the hash value prefilled to the hidden element
$dom = new Zend_Dom_Query($html);
$csrf = $dom->query('#csrf')->current()->getAttribute('value');
// reset tester for one more request
$this->resetRequest()
->resetResponse();
// now include $csrf value parsed from form, to the next request
$this->request->setMethod('POST')
->setPost(array('title'=>'MyNewTitle',
'body'=>'Body',
'csrf'=>$csrf));
$this->dispatch('/form-page');
// ...
}
The correct hash is stored in the session, and the Hash form element has a Zend_Session_Namespace instance which contains the namespace for the hash.
To unit test the element, you would replace the Zend_Session_Namespace instance in the element (with setSession) with one you create yourself which contains the correct hash (the hash is stored in key "hash")
For further examples you could probably look at the Zend Framework unit tests for the Zend_Form_Element_Hash class. I would assume they have had to deal with this as well.
I set an environment variable in my Apache vhost file, which tells the code which server it's running on:
development, staging, or production
The line for the vhost file is:
SetEnv SITE_ENV "dev"
Then I just make my forms react to the appropriate environment:
if($_SERVER['SITE_ENV']!='dev')
{
$form_element->addValidator($csrf_validator);
}
I use this same technique for lots of stuff. For example, if it IS dev, I redirect all outgoing email to me, etc.
I answered a more recent question similar to this one. I'm putting my answer here as well in case it helps anybody in the future.
I recently found a great way of testing forms with hash elements. This will use a mock object to stub away the hash element and you won't have to worry about it. You won't even have to do a session_start or anything this way. You won't have to 'prerender' the form either.
First create a 'stub' class like so
class My_Form_Element_HashStub extends Zend_Form_Element_Hash
{
public function __construct(){}
}
Then, add the following to the form somewhere.
class MyForm extends Zend_Form
{
protected $_hashElement;
public function setHashElement( Zend_Form_Hash_Element $hash )
{
$this->_hashElement = $hash;
return $this;
}
protected function _getHashElement( $name = 'hashElement' )
{
if( !isset( $this->_hashElement )
{
if( isset( $name ) )
{
$element = new Zend_Form_Element_Hash( $name,
array( 'id' => $name ) );
}
else
{
$element = new Zend_Form_Element_Hash( 'hashElement',
array( 'id' => 'hashElement' ) );
}
$this->setHashElement( $element );
return $this->_hashElement;
}
}
/**
* In your init method you can now add the hash element like below
*/
public function init()
{
//other code
$this->addElement( $this->_getHashElement( 'myotherhashelementname' );
//other code
}
}
The set method is there just for testing purposes really. You probably won't use it at all during real use but now in phpunit you can right the following.
class My_Form_LoginTest extends PHPUnit_Framework_TestCase
{
/**
*
* #var My_Form_Login
*/
protected $_form;
/**
*
* #var PHPUnit_Framework_MockObject_MockObject
*/
protected $_hash;
public function setUp()
{
parent::setUp();
$this->_hash = $this->getMock( 'My_Form_Element_HashStub' );
$this->_form = new My_Form_Login( array(
'action' => '/',
'hashElement' => $this->_hash
}
public function testTrue()
{
//The hash element will now always validate to true
$this->_hash
->expects( $this->any() )
->method( 'isValid' )
->will( $this->returnValue( true ) );
//OR if you need it to validate to false
$this->_hash
->expects( $this->any() )
->method( 'isValid' )
->will( $this->returnValue( true ) );
}
}
You HAVE to create your own stub. You can't just call the phpunit method getMockObject() because that will directly extend the hash element and the normal hash element does 'evil' stuff in its constructor.
With this method you don't even need to be connected to a database to test your forms! It took me a while to think of this.
If you want, you can push the setHashElement() method ( along with the variable and the get method ) into some FormAbstract base class.
REMEMBER, in phpunit you HAVE to pass the hash element during form construction. If you don't, your init() method will get called before your stub hash can be set with the set method and you'll end up using the regular hash element. You'll know you're using the regular hash element because you'll probably get some session error if you're NOT connected to a database.
Let me know if you find this helpful or if you use it.
Solution for ZF2 is creating your form in test, and getting value from your csrf form element:
$form = new \User\Form\SignupForm('create-user');
$data = [
'security' => $form->get('security')->getValue(),
'email' => 'test#test.com',
'password' => '123456',
'repeat-password' => '123456',
];
$this->dispatch('/signup', 'POST', $data);