1

I have followed the zf2 album example. I am now trying to integrate the HTML Purifier.

This is the Module https://github.com/juriansluiman/Soflomo-Purifier#injecting-the-filtermanager

This is the way I have constructed my inputfilter.
http://framework.zend.com/manual/current/en/user-guide/forms-and-actions.html

namespace Album\Model;

 // Add these import statements
 use Zend\InputFilter\InputFilter;
 use Zend\InputFilter\InputFilterAwareInterface;
 use Zend\InputFilter\InputFilterInterface;

 class Album implements InputFilterAwareInterface
 {
     public $id;
     public $artist;
     public $title;
     protected $inputFilter;                       // <-- Add this variable

     public function exchangeArray($data)
     {
         $this->id     = (isset($data['id']))     ? $data['id']     : null;
         $this->artist = (isset($data['artist'])) ? $data['artist'] : null;
         $this->title  = (isset($data['title']))  ? $data['title']  : null;
     }

     // Add content to these methods:
     public function setInputFilter(InputFilterInterface $inputFilter)
     {
         throw new \Exception("Not used");
     }

     public function getInputFilter()
     {
         if (!$this->inputFilter) {
             $inputFilter = new InputFilter();

             $inputFilter->add(array(
                 'name'     => 'id',
                 'required' => true,
                 'filters'  => array(
                     array('name' => 'Int'),
                 ),
             ));

             $inputFilter->add(array(
                 'name'     => 'artist',
                 'required' => true,
                 'filters'  => array(
                     array('name' => 'StripTags'),
                     array('name' => 'StringTrim'),
                 ),
                 'validators' => array(
                     array(
                         'name'    => 'StringLength',
                         'options' => array(
                             'encoding' => 'UTF-8',
                             'min'      => 1,
                             'max'      => 100,
                         ),
                     ),
                 ),
             ));

             $inputFilter->add(array(
                 'name'     => 'title',
                 'required' => true,
                 'filters'  => array(
                     array('name' => 'StripTags'),
                     array('name' => 'StringTrim'),
                 ),
                 'validators' => array(
                     array(
                         'name'    => 'StringLength',
                         'options' => array(
                             'encoding' => 'UTF-8',
                             'min'      => 1,
                             'max'      => 100,
                         ),
                     ),
                 ),
             ));

             $this->inputFilter = $inputFilter;
         }

         return $this->inputFilter;
     }
 }

I am getting the following error.

As such, you get a ServiceNotFoundException: Zend\Filter\FilterPluginManager::get was unable to fetch or create an instance for htmlpurifier. This means the filter plugin manager was lazily instantiated, and does not know about the htmlpurifier plugin.

What is the proper way to construct my input filter to take advantage of this module. Many Thanks, Matt

1 Answer 1

1

The problem you're experiencing is caused exactly by what is noted in SoflomoPurifier documentation: since you're manually instantiating with new InputFilter, that instance is never wired with the configuration provided by additional modules.

To ensure this wiring happens, I would suggest to create a new InputFilter subclass and put your all the InputFilter::add() calls into its init() method:

use Zend\InputFilter\InputFilter:

class AlbumInputFilter extends InputFilter
{
    public function init()
    {
        $this->add(array(
            'name'     => 'id',
            'required' => true,
            'filters'  => array(
                array('name' => 'Int'),
            ),
         ));

        $this->add(array(
            'name'     => 'artist',
            'required' => true,
            'filters'  => array(
                array('name' => 'StripTags'),
                array('name' => 'StringTrim'),
            ),
            'validators' => array(
                array(
                    'name'    => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min'      => 1,
                        'max'      => 100,
                    ),
                ),
            ),
         ));

        $this->add(array(
            'name'     => 'title',
            'required' => true,
            'filters'  => array(
                array('name' => 'StripTags'),
                array('name' => 'StringTrim'),
            ),
            'validators' => array(
                array(
                    'name'    => 'StringLength',
                    'options' => array(
                        'encoding' => 'UTF-8',
                        'min'      => 1,
                        'max'      => 100,
                    ),
                ),
            ),
         ));
    }
}

change your Album model constructor to use constructor injection:

use Zend\InputFilter\InputFilterInterface;

class Album
{
    // etc etc

    public function __construct(InputFilterInterface $inputFilter)
    {
        $this->inputFilter = $inputFilter;
    }

    // etc etc
}

and then use a factory to inject it:

// in your Module.php

public function getServiceConfig()
{
    return [
        'factories' => [
            'AlbumFactory' => function($serviceManager) {
                $inputFilterManager = $serviceManager->get('InputFilterManager');
                return function() use ($inputFilterManager) {
                    $inputFilter = $inputFilterManager->get(AlbumInputFilter::class);
                    return new Album($inputFilter)
                }
            }
        ]
    ];
}

invoking InputFilterPluginManager::get() with an input filter FQCN will automatically invoke its constructor, wire it up with other modules, and then invoke its init() method.

so now, rather than using $album = new Album, you should use the AlbumFactory service to create albums with their input filter correctly injected:

$createAlbum = $serviceManager->get('AlbumFactory');
$album = $createAlbum()

obviously you are advised to inject this factory inside any consumer (i.e. controllers) instead of pulling it from the service manager, and possibly refactor the anonymous function into a dedicated factory class.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your response. I am working on implementing the above but am having trouble in the Module file. My service manager is null. Do I need to change my configuration in the module.config file?
This is what I currently have... 'service_manager' => array( 'abstract_factories' => array( 'Zend\Cache\Service\StorageCacheAbstractServiceFactory', 'Zend\Log\LoggerAbstractServiceFactory', ), 'factories' => array( 'translator' => 'Zend\Mvc\Service\TranslatorServiceFactory', ), 'services' => array( 'translator' => 'Zend\Mvc\Service\TranslatorServiceFactory', ),
Stefano, I got it to work, I ended up putting the album factory in the factories array as opposed to the service array. Is this an issue? Or do I need to keep it in the services? How do I get the service manager in the services if this is the case. Thank you.
actually it was an error on my part, it has to go in the factories key :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.