1<?php
2
3/**
4 * Injector that removes spans with no attributes
5 */
6class HTMLPurifier_Injector_RemoveSpansWithoutAttributes extends HTMLPurifier_Injector
7{
8    /**
9     * @type string
10     */
11    public $name = 'RemoveSpansWithoutAttributes';
12
13    /**
14     * @type array
15     */
16    public $needed = array('span');
17
18    /**
19     * @type HTMLPurifier_AttrValidator
20     */
21    private $attrValidator;
22
23    /**
24     * Used by AttrValidator.
25     * @type HTMLPurifier_Config
26     */
27    private $config;
28
29    /**
30     * @type HTMLPurifier_Context
31     */
32    private $context;
33
34    /**
35     * @type SplObjectStorage
36     */
37    private $markForDeletion;
38
39    public function __construct()
40    {
41        $this->markForDeletion = new SplObjectStorage();
42    }
43
44    public function prepare($config, $context)
45    {
46        $this->attrValidator = new HTMLPurifier_AttrValidator();
47        $this->config = $config;
48        $this->context = $context;
49        return parent::prepare($config, $context);
50    }
51
52    /**
53     * @param HTMLPurifier_Token $token
54     */
55    public function handleElement(&$token)
56    {
57        if ($token->name !== 'span' || !$token instanceof HTMLPurifier_Token_Start) {
58            return;
59        }
60
61        // We need to validate the attributes now since this doesn't normally
62        // happen until after MakeWellFormed. If all the attributes are removed
63        // the span needs to be removed too.
64        $this->attrValidator->validateToken($token, $this->config, $this->context);
65        $token->armor['ValidateAttributes'] = true;
66
67        if (!empty($token->attr)) {
68            return;
69        }
70
71        $nesting = 0;
72        while ($this->forwardUntilEndToken($i, $current, $nesting)) {
73        }
74
75        if ($current instanceof HTMLPurifier_Token_End && $current->name === 'span') {
76            // Mark closing span tag for deletion
77            $this->markForDeletion->attach($current);
78            // Delete open span tag
79            $token = false;
80        }
81    }
82
83    /**
84     * @param HTMLPurifier_Token $token
85     */
86    public function handleEnd(&$token)
87    {
88        if ($this->markForDeletion->contains($token)) {
89            $this->markForDeletion->detach($token);
90            $token = false;
91        }
92    }
93}
94
95// vim: et sw=4 sts=4
96