diff --git a/Module.php b/Module.php index 01866da..2f42500 100644 --- a/Module.php +++ b/Module.php @@ -79,10 +79,7 @@ public function getFilterConfig() { return array( 'factories' => array( - 'htmlpurifier' => function($sl) { - $purifier = $sl->getServiceLocator()->get('HTMLPurifier'); - return new Filter\Purifier($purifier); - }, + 'htmlpurifier' => 'Soflomo\Purifier\Factory\PurifierFilterFactory' ), ); } diff --git a/composer.json b/composer.json index c96a6d4..9cdcc93 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,10 @@ "zendframework/zendframework": "2.*", "ezyang/htmlpurifier": ">=4.5.0" }, + "require-dev": + { + "phpunit/phpunit": "~3.7" + }, "autoload": { "psr-0": { "Soflomo\\Purifier": "src/" diff --git a/src/Soflomo/Purifier/Factory/HtmlPurifierFactory.php b/src/Soflomo/Purifier/Factory/HtmlPurifierFactory.php index 180beab..a7a3326 100644 --- a/src/Soflomo/Purifier/Factory/HtmlPurifierFactory.php +++ b/src/Soflomo/Purifier/Factory/HtmlPurifierFactory.php @@ -65,7 +65,6 @@ public function createService(ServiceLocatorInterface $sl) $config->set($key, $value); } - $purifier = new HTMLPurifier($config); - return $purifier; + return new HTMLPurifier($config); } } diff --git a/src/Soflomo/Purifier/Factory/PurifierFilterFactory.php b/src/Soflomo/Purifier/Factory/PurifierFilterFactory.php new file mode 100644 index 0000000..e59b340 --- /dev/null +++ b/src/Soflomo/Purifier/Factory/PurifierFilterFactory.php @@ -0,0 +1,41 @@ +options = $options; + } + + /** + * (non-PHPdoc) + * @see \Zend\ServiceManager\FactoryInterface::createService() + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $purifier = $serviceLocator->getServiceLocator()->get('HTMLPurifier'); + + $filter = new Purifier($purifier); + + if ($this->options === null || empty($this->options)) { + return $filter; + } else { + return $filter->setOptions($this->options); + } + } +} diff --git a/src/Soflomo/Purifier/Filter/Purifier.php b/src/Soflomo/Purifier/Filter/Purifier.php index 3d52597..a23261e 100644 --- a/src/Soflomo/Purifier/Filter/Purifier.php +++ b/src/Soflomo/Purifier/Filter/Purifier.php @@ -4,26 +4,63 @@ use HTMLPurifier; use Zend\Filter\FilterInterface; +use Zend\Filter\AbstractFilter; -class Purifier implements FilterInterface +class Purifier extends AbstractFilter implements FilterInterface { protected $purifier; + /** + * Comma seperated values as string + * + * @var string + */ + protected $allowedElements; + + /** + * @param HTMLPurifier $purifier + */ public function __construct(HTMLPurifier $purifier) { $this->purifier = $purifier; } + /** + * Returns the purifier with config allowed elements added if specified + * + * @return HTMLPurifier + */ protected function getPurifier() { return $this->purifier; } - + /** * {@inheritdocs} */ public function filter($value) { - return $this->getPurifier()->purify($value); + $purifier = $this->getPurifier(); + + if ($this->allowedElements !== null) { + $config = \HTMLPurifier_Config::createDefault(); + + $config = $config->inherit($purifier->config); + $config->set('HTML.AllowedElements', $this->allowedElements); + + return $purifier->purify($value, $config); + } + + return $purifier->purify($value); + } + + /** + * Array of values to be provided to HTMLPurifier_Config Attr.AllowedClasses + * + * @param array $allowedClasses + */ + public function setAllowedElements($allowedElements) + { + $this->allowedElements = $allowedElements; } } \ No newline at end of file diff --git a/src/Soflomo/Purifier/Test/Form/PurifierTestForm.php b/src/Soflomo/Purifier/Test/Form/PurifierTestForm.php new file mode 100644 index 0000000..71164b9 --- /dev/null +++ b/src/Soflomo/Purifier/Test/Form/PurifierTestForm.php @@ -0,0 +1,54 @@ +name = 'test'; + parent::__construct($this->name); + } + + /** + * Provide default input rules for this element + * + * Attaches strip tags filter + * + * @return array + */ + public function getInputFilterSpecification() + { + return [ + 'test' => [ + 'required' => false, + 'filters' => [ + array('name' => 'htmlpurifier', + 'options' => [ + 'allowed_elements' => 'p' + ] + ), + ], + ] + ]; + } + + + + public function init() + { + $this->add(array( + 'name' => 'test', + 'type' => 'Textarea', + + )); + } +} \ No newline at end of file diff --git a/src/Soflomo/Purifier/View/Helper/Purifier.php b/src/Soflomo/Purifier/View/Helper/Purifier.php index d3cc5d2..0b277ff 100644 --- a/src/Soflomo/Purifier/View/Helper/Purifier.php +++ b/src/Soflomo/Purifier/View/Helper/Purifier.php @@ -45,18 +45,33 @@ class Purifier extends AbstractHelper { + /** + * @var HTMLPurifier + */ protected $purifier; + /** + * @param HTMLPurifier $purifier + */ public function __construct(HTMLPurifier $purifier) { $this->purifier = $purifier; } + /** + * Getter for purifier + * + * @return HTMLPurifier + */ protected function getPurifier() { return $this->purifier; } + /** + * @param string $html + * @return \Soflomo\Purifier\View\Helper\Purifier|Ambigous + */ public function __invoke($html = null) { if (null === $html) { @@ -66,6 +81,11 @@ public function __invoke($html = null) return $this->purify($html); } + /** + * Purifies the html string + * + * @param string $html + */ public function purify($html) { return $this->getPurifier()->purify($html); diff --git a/test/Bootstrap.php b/test/Bootstrap.php new file mode 100644 index 0000000..4ec3789 --- /dev/null +++ b/test/Bootstrap.php @@ -0,0 +1,108 @@ + array( + 'module_paths' => explode(PATH_SEPARATOR, $zf2ModulePaths), + ), + ); + + $config = ArrayUtils::merge($baseConfig, $testConfig); + //exit(var_dump($config)); + $serviceManager = new ServiceManager(new ServiceManagerConfig()); + $serviceManager->setService('ApplicationConfig', $config); + $serviceManager->get('ModuleManager')->loadModules(); + + static::$serviceManager = $serviceManager; + static::$config = $config; + } + + public static function getServiceManager() + { + return static::$serviceManager; + } + + public static function getConfig() + { + return static::$config; + } + + protected static function initAutoloader() + { + $vendorPath = static::findParentPath('vendor'); + + if (is_readable($vendorPath . '/autoload.php')) { + $loader = include $vendorPath . '/autoload.php'; + } else { + $zf2Path = getenv('ZF2_PATH') ?: (defined('ZF2_PATH') ? ZF2_PATH : (is_dir($vendorPath . '/ZF2/library') ? $vendorPath . '/ZF2/library' : false)); + + if (!$zf2Path) { + throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.'); + } + + include $zf2Path . '/Zend/Loader/AutoloaderFactory.php'; + + } + + } + + protected static function findParentPath($path) + { + $dir = __DIR__; + $previousDir = '.'; + while (!is_dir($dir . '/' . $path)) { + $dir = dirname($dir); + if ($previousDir === $dir) return false; + $previousDir = $dir; + } + return $dir . '/' . $path; + } + +} + +Bootstrap::init(); \ No newline at end of file diff --git a/test/PurifierTest/Filter/PurifierTest.php b/test/PurifierTest/Filter/PurifierTest.php new file mode 100644 index 0000000..0efd9a7 --- /dev/null +++ b/test/PurifierTest/Filter/PurifierTest.php @@ -0,0 +1,81 @@ +Paragraph

Whitehat Header

Blackhat Header

'; + + /** + * Setup the filter and services as close as posisble to + * during an application request + */ + public function setUp() + { + parent::setUp(); + $init = \Zend\Mvc\Application::init(\PurifierTest\Bootstrap::getConfig()); + + $serviceManager = \PurifierTest\Bootstrap::getServiceManager(); + $filterChain = new \Zend\Filter\FilterChain(); + $this->filterManager = $filterChain->getPluginManager(); + $filterManager = $filterChain->getPluginManager(); + $this->filterManager->setServiceLocator($serviceManager); + + $filter = $serviceManager->get('htmlpurifier'); + + $this->filterManager->setFactory('htmlpurifier', 'Soflomo\Purifier\Factory\PurifierFilterFactory'); + $this->filter = $this->filterManager->get('htmlpurifier'); + + $this->formManager = $serviceManager->get('FormElementManager'); + } + + public function testCanAcceptAllowedElements() + { + $this->filter->setOptions(['allowed_elements' => 'p']); + $result = $this->filter->filter($this->htmlTestString); + $this->assertEquals("

Paragraph

Whitehat HeaderBlackhat Header", $result); + + $result = $this->filter->filter($this->htmlTestString); + } + + public function testConfigAndFilterState() + { + $this->filter->setOptions(['allowed_elements' => 'p']); + $result = $this->filter->filter($this->htmlTestString); + $this->assertEquals("

Paragraph

Whitehat HeaderBlackhat Header", $result); + + $this->filterTwo = $this->filterManager->get('htmlpurifier'); + + $result = $this->filterTwo->filter($this->htmlTestString); + $this->assertEquals("

Paragraph

Whitehat Header

Blackhat Header

", $result); + } + + public function testFormManagerInit() + { + $this->formManager->setInvokableClass('TestForm', '\Soflomo\Purifier\Test\Form\PurifierTestForm'); + + $form = $this->formManager->get('TestForm'); + + $form->setData(['test' => $this->htmlTestString]); + $form->isValid(); + + $this->assertEquals("

Paragraph

Whitehat HeaderBlackhat Header", $form->getData()['test']); + } +} \ No newline at end of file diff --git a/test/config/TestConfig.php.dist b/test/config/TestConfig.php.dist new file mode 100644 index 0000000..8a475fd --- /dev/null +++ b/test/config/TestConfig.php.dist @@ -0,0 +1,16 @@ + array( + 'Soflomo\Purifier' + ), + 'module_listener_options' => array( + 'config_glob_paths' => array( + __DIR__.'/{,*.}{global,local}.php', + __DIR__.'/../../config/{*}.php', + ), + 'module_paths' => array( + 'module', + 'vendor', + ), + ), +); \ No newline at end of file diff --git a/test/phpunit.xml.dist b/test/phpunit.xml.dist new file mode 100644 index 0000000..7e119f7 --- /dev/null +++ b/test/phpunit.xml.dist @@ -0,0 +1,15 @@ + + + + + + ./PurifierTest + + + + + + ../src/Purifier + + + \ No newline at end of file