1: | <?php
|
2: |
|
3: | |
4: | |
5: | |
6: | |
7: | |
8: |
|
9: | class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
|
10: | {
|
11: | |
12: | |
13: |
|
14: | public $name = 'AutoParagraph';
|
15: |
|
16: | |
17: | |
18: |
|
19: | public $needed = array('p');
|
20: |
|
21: | |
22: | |
23: |
|
24: | private function _pStart()
|
25: | {
|
26: | $par = new HTMLPurifier_Token_Start('p');
|
27: | $par->armor['MakeWellFormed_TagClosedError'] = true;
|
28: | return $par;
|
29: | }
|
30: |
|
31: | |
32: | |
33: |
|
34: | public function handleText(&$token)
|
35: | {
|
36: | $text = $token->data;
|
37: |
|
38: | if ($this->allowsElement('p')) {
|
39: | if (empty($this->currentNesting) || strpos($text, "\n\n") !== false) {
|
40: |
|
41: |
|
42: |
|
43: |
|
44: |
|
45: | $i = $nesting = null;
|
46: | if (!$this->forwardUntilEndToken($i, $current, $nesting) && $token->is_whitespace) {
|
47: |
|
48: |
|
49: |
|
50: | } else {
|
51: | if (!$token->is_whitespace || $this->_isInline($current)) {
|
52: |
|
53: |
|
54: |
|
55: |
|
56: |
|
57: |
|
58: |
|
59: |
|
60: | $token = array($this->_pStart());
|
61: | $this->_splitText($text, $token);
|
62: | } else {
|
63: |
|
64: |
|
65: | }
|
66: | }
|
67: | } else {
|
68: |
|
69: |
|
70: |
|
71: |
|
72: |
|
73: | if ($this->_pLookAhead()) {
|
74: |
|
75: |
|
76: |
|
77: |
|
78: |
|
79: |
|
80: | $token = array($this->_pStart(), $token);
|
81: | } else {
|
82: |
|
83: |
|
84: |
|
85: |
|
86: |
|
87: | }
|
88: | }
|
89: |
|
90: | } elseif (!empty($this->currentNesting) &&
|
91: | $this->currentNesting[count($this->currentNesting) - 1]->name == 'p') {
|
92: |
|
93: |
|
94: |
|
95: |
|
96: |
|
97: | $token = array();
|
98: | $this->_splitText($text, $token);
|
99: |
|
100: | } else {
|
101: |
|
102: |
|
103: |
|
104: |
|
105: |
|
106: | }
|
107: | }
|
108: |
|
109: | |
110: | |
111: |
|
112: | public function handleElement(&$token)
|
113: | {
|
114: |
|
115: |
|
116: | if ($this->allowsElement('p')) {
|
117: | if (!empty($this->currentNesting)) {
|
118: | if ($this->_isInline($token)) {
|
119: |
|
120: |
|
121: |
|
122: |
|
123: | $i = null;
|
124: | $this->backward($i, $prev);
|
125: |
|
126: | if (!$prev instanceof HTMLPurifier_Token_Start) {
|
127: |
|
128: | if ($prev instanceof HTMLPurifier_Token_Text &&
|
129: | substr($prev->data, -2) === "\n\n"
|
130: | ) {
|
131: |
|
132: |
|
133: |
|
134: | $token = array($this->_pStart(), $token);
|
135: | } else {
|
136: |
|
137: |
|
138: |
|
139: |
|
140: |
|
141: |
|
142: | }
|
143: | } else {
|
144: |
|
145: |
|
146: |
|
147: | if ($this->_pLookAhead()) {
|
148: |
|
149: |
|
150: | $token = array($this->_pStart(), $token);
|
151: | } else {
|
152: |
|
153: |
|
154: |
|
155: |
|
156: |
|
157: | }
|
158: | }
|
159: | } else {
|
160: |
|
161: |
|
162: | }
|
163: | } else {
|
164: | if ($this->_isInline($token)) {
|
165: |
|
166: |
|
167: |
|
168: |
|
169: | $token = array($this->_pStart(), $token);
|
170: | } else {
|
171: |
|
172: |
|
173: | }
|
174: |
|
175: | $i = null;
|
176: | if ($this->backward($i, $prev)) {
|
177: | if (!$prev instanceof HTMLPurifier_Token_Text) {
|
178: |
|
179: |
|
180: |
|
181: |
|
182: | if (!is_array($token)) {
|
183: | $token = array($token);
|
184: | }
|
185: | array_unshift($token, new HTMLPurifier_Token_Text("\n\n"));
|
186: | } else {
|
187: |
|
188: |
|
189: |
|
190: |
|
191: |
|
192: |
|
193: | }
|
194: | }
|
195: | }
|
196: | } else {
|
197: |
|
198: |
|
199: |
|
200: |
|
201: | }
|
202: | }
|
203: |
|
204: | |
205: | |
206: | |
207: | |
208: | |
209: | |
210: | |
211: |
|
212: | private function _splitText($data, &$result)
|
213: | {
|
214: | $raw_paragraphs = explode("\n\n", $data);
|
215: | $paragraphs = array();
|
216: | $needs_start = false;
|
217: | $needs_end = false;
|
218: |
|
219: | $c = count($raw_paragraphs);
|
220: | if ($c == 1) {
|
221: |
|
222: |
|
223: | $result[] = new HTMLPurifier_Token_Text($data);
|
224: | return;
|
225: | }
|
226: | for ($i = 0; $i < $c; $i++) {
|
227: | $par = $raw_paragraphs[$i];
|
228: | if (trim($par) !== '') {
|
229: | $paragraphs[] = $par;
|
230: | } else {
|
231: | if ($i == 0) {
|
232: |
|
233: | if (empty($result)) {
|
234: |
|
235: |
|
236: |
|
237: |
|
238: | $result[] = new HTMLPurifier_Token_End('p');
|
239: | $result[] = new HTMLPurifier_Token_Text("\n\n");
|
240: |
|
241: |
|
242: |
|
243: |
|
244: |
|
245: | $needs_start = true;
|
246: | } else {
|
247: |
|
248: |
|
249: |
|
250: | array_unshift($result, new HTMLPurifier_Token_Text("\n\n"));
|
251: | }
|
252: | } elseif ($i + 1 == $c) {
|
253: |
|
254: |
|
255: | $needs_end = true;
|
256: | }
|
257: | }
|
258: | }
|
259: |
|
260: |
|
261: |
|
262: | if (empty($paragraphs)) {
|
263: | return;
|
264: | }
|
265: |
|
266: |
|
267: | if ($needs_start) {
|
268: | $result[] = $this->_pStart();
|
269: | }
|
270: |
|
271: |
|
272: | foreach ($paragraphs as $par) {
|
273: | $result[] = new HTMLPurifier_Token_Text($par);
|
274: | $result[] = new HTMLPurifier_Token_End('p');
|
275: | $result[] = new HTMLPurifier_Token_Text("\n\n");
|
276: | $result[] = $this->_pStart();
|
277: | }
|
278: |
|
279: |
|
280: |
|
281: |
|
282: | array_pop($result);
|
283: |
|
284: |
|
285: |
|
286: | if (!$needs_end) {
|
287: | array_pop($result);
|
288: | array_pop($result);
|
289: | }
|
290: | }
|
291: |
|
292: | |
293: | |
294: | |
295: | |
296: | |
297: |
|
298: | private function _isInline($token)
|
299: | {
|
300: | return isset($this->htmlDefinition->info['p']->child->elements[$token->name]);
|
301: | }
|
302: |
|
303: | |
304: | |
305: | |
306: | |
307: |
|
308: | private function _pLookAhead()
|
309: | {
|
310: | if ($this->currentToken instanceof HTMLPurifier_Token_Start) {
|
311: | $nesting = 1;
|
312: | } else {
|
313: | $nesting = 0;
|
314: | }
|
315: | $ok = false;
|
316: | $i = null;
|
317: | while ($this->forwardUntilEndToken($i, $current, $nesting)) {
|
318: | $result = $this->_checkNeedsP($current);
|
319: | if ($result !== null) {
|
320: | $ok = $result;
|
321: | break;
|
322: | }
|
323: | }
|
324: | return $ok;
|
325: | }
|
326: |
|
327: | |
328: | |
329: | |
330: | |
331: | |
332: |
|
333: | private function _checkNeedsP($current)
|
334: | {
|
335: | if ($current instanceof HTMLPurifier_Token_Start) {
|
336: | if (!$this->_isInline($current)) {
|
337: |
|
338: |
|
339: |
|
340: | return false;
|
341: | }
|
342: | } elseif ($current instanceof HTMLPurifier_Token_Text) {
|
343: | if (strpos($current->data, "\n\n") !== false) {
|
344: |
|
345: |
|
346: | return true;
|
347: | } else {
|
348: |
|
349: |
|
350: | }
|
351: | }
|
352: | return null;
|
353: | }
|
354: | }
|
355: |
|
356: |
|
357: | |