Test Setup Failed
Branch gcconnex (718fe4)
by Ilia
21:13
created

MarkdownExtra_Parser   D

Complexity

Total Complexity 140

Size/Duplication

Total Lines 1556
Duplicated Lines 21.34 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 332
loc 1556
rs 4.4102
c 0
b 0
f 0
wmc 140
lcom 1
cbo 1

40 Methods

Rating   Name   Duplication   Size   Complexity  
B MarkdownExtra_Parser() 0 28 1
A setup() 0 21 3
A teardown() 0 13 1
C doExtraAttributes() 0 34 8
B stripLinkDefinitions() 35 35 1
A _stripLinkDefinitions_callback() 0 8 2
B hashHTMLBlocks() 0 25 2
D _hashHTMLBlocks_inMarkdown() 24 244 24
D _hashHTMLBlocks_inHTML() 2 173 19
A hashClean() 0 8 1
A doAnchors() 71 71 2
B _doAnchors_reference_callback() 5 36 5
A _doAnchors_inline_callback() 22 22 3
A doImages() 56 56 1
B _doImages_reference_callback() 5 30 5
A _doImages_inline_callback() 19 19 3
B doHeaders() 0 40 1
A _doHeaders_callback_setext() 2 8 4
A _doHeaders_callback_atx() 0 6 1
A doTables() 0 61 1
A _doTable_leadingPipe_callback() 0 10 1
B _doTable_callback() 0 58 8
B doDefLists() 0 42 1
A _doDefLists_callback() 0 10 1
B processDefListItems() 0 43 1
A _processDefListItems_callback_dt() 0 9 2
A _processDefListItems_callback_dd() 10 18 3
B doFencedCodeBlocks() 39 39 1
B _doFencedCodeBlocks_callback() 0 21 6
A _doFencedCodeBlocks_newlines() 0 4 1
B formParagraphs() 0 34 3
B stripFootnotes() 27 27 1
A _stripFootnotes_callback() 0 5 1
A doFootnotes() 0 10 2
B appendFootnotes() 0 64 7
B _appendFootnotes_callback() 0 41 5
A stripAbbreviations() 15 15 1
A _stripAbbreviations_callback() 0 9 2
A doAbbreviations() 0 16 2
A _doAbbreviations_callback() 0 14 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like MarkdownExtra_Parser often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MarkdownExtra_Parser, and based on these observations, apply Extract Interface, too.

1
<?php
2
#
3
# Markdown Extra  -  A text-to-HTML conversion tool for web writers
4
#
5
# PHP Markdown & Extra  
6
# Copyright (c) 2004-2013 Michel Fortin  
7
# <http://michelf.ca/projects/php-markdown/>
8
#
9
# Original Markdown  
10
# Copyright (c) 2004-2006 John Gruber  
11
# <http://daringfireball.net/projects/markdown/>
12
#
13
14
15
define( 'MARKDOWN_VERSION',  "1.0.2" ); # 29 Nov 2013
16
define( 'MARKDOWNEXTRA_VERSION',  "1.2.8" ); # 29 Nov 2013
17
18
19
#
20
# Global default settings:
21
#
22
23
# Change to ">" for HTML output
24
@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX',  " />");
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
25
26
# Define the width of a tab for code blocks.
27
@define( 'MARKDOWN_TAB_WIDTH',     4 );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
28
29
# Optional title attribute for footnote links and backlinks.
30
@define( 'MARKDOWN_FN_LINK_TITLE',         "" );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
31
@define( 'MARKDOWN_FN_BACKLINK_TITLE',     "" );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
32
33
# Optional class attribute for footnote links and backlinks.
34
@define( 'MARKDOWN_FN_LINK_CLASS',         "" );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
35
@define( 'MARKDOWN_FN_BACKLINK_CLASS',     "" );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
36
37
# Optional class prefix for fenced code block.
38
@define( 'MARKDOWN_CODE_CLASS_PREFIX',     "" );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
39
40
# Class attribute for code blocks goes on the `code` tag;
41
# setting this to true will put attributes on the `pre` tag instead.
42
@define( 'MARKDOWN_CODE_ATTR_ON_PRE',   false );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
43
44
45
#
46
# WordPress settings:
47
#
48
49
# Change to false to remove Markdown from posts and/or comments.
50
@define( 'MARKDOWN_WP_POSTS',      true );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
51
@define( 'MARKDOWN_WP_COMMENTS',   true );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
52
53
54
55
### Standard Function Interface ###
56
57
@define( 'MARKDOWN_PARSER_CLASS',  'MarkdownExtra_Parser' );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
58
59
function Markdown($text) {
60
#
61
# Initialize the parser and return the result of its transform method.
62
#
63
	# Setup static parser variable.
64
	static $parser;
65
	if (!isset($parser)) {
66
		$parser_class = MARKDOWN_PARSER_CLASS;
67
		$parser = new $parser_class;
68
	}
69
70
	# Transform text using parser.
71
	return $parser->transform($text);
72
}
73
74
75
### WordPress Plugin Interface ###
76
77
/*
78
Plugin Name: Markdown Extra
79
Plugin Name: Markdown
80
Plugin URI: http://michelf.ca/projects/php-markdown/
81
Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.ca/projects/php-markdown/">More...</a>
82
Version: 1.2.8
83
Author: Michel Fortin
84
Author URI: http://michelf.ca/
85
*/
86
87
if (isset($wp_version)) {
88
	# More details about how it works here:
89
	# <http://michelf.ca/weblog/2005/wordpress-text-flow-vs-markdown/>
90
	
91
	# Post content and excerpts
92
	# - Remove WordPress paragraph generator.
93
	# - Run Markdown on excerpt, then remove all tags.
94
	# - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
95
	if (MARKDOWN_WP_POSTS) {
96
		remove_filter('the_content',     'wpautop');
97
        remove_filter('the_content_rss', 'wpautop');
98
		remove_filter('the_excerpt',     'wpautop');
99
		add_filter('the_content',     'mdwp_MarkdownPost', 6);
100
        add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
101
		add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
102
		add_filter('get_the_excerpt', 'trim', 7);
103
		add_filter('the_excerpt',     'mdwp_add_p');
104
		add_filter('the_excerpt_rss', 'mdwp_strip_p');
105
		
106
		remove_filter('content_save_pre',  'balanceTags', 50);
107
		remove_filter('excerpt_save_pre',  'balanceTags', 50);
108
		add_filter('the_content',  	  'balanceTags', 50);
109
		add_filter('get_the_excerpt', 'balanceTags', 9);
110
	}
111
	
112
	# Add a footnote id prefix to posts when inside a loop.
113
	function mdwp_MarkdownPost($text) {
114
		static $parser;
115
		if (!$parser) {
116
			$parser_class = MARKDOWN_PARSER_CLASS;
117
			$parser = new $parser_class;
118
		}
119
		if (is_single() || is_page() || is_feed()) {
120
			$parser->fn_id_prefix = "";
121
		} else {
122
			$parser->fn_id_prefix = get_the_ID() . ".";
123
		}
124
		return $parser->transform($text);
125
	}
126
	
127
	# Comments
128
	# - Remove WordPress paragraph generator.
129
	# - Remove WordPress auto-link generator.
130
	# - Scramble important tags before passing them to the kses filter.
131
	# - Run Markdown on excerpt then remove paragraph tags.
132
	if (MARKDOWN_WP_COMMENTS) {
133
		remove_filter('comment_text', 'wpautop', 30);
134
		remove_filter('comment_text', 'make_clickable');
135
		add_filter('pre_comment_content', 'Markdown', 6);
136
		add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
137
		add_filter('pre_comment_content', 'mdwp_show_tags', 12);
138
		add_filter('get_comment_text',    'Markdown', 6);
139
		add_filter('get_comment_excerpt', 'Markdown', 6);
140
		add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
141
	
142
		global $mdwp_hidden_tags, $mdwp_placeholders;
143
		$mdwp_hidden_tags = explode(' ',
144
			'<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
145
		$mdwp_placeholders = explode(' ', str_rot13(
146
			'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
147
			'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
148
	}
149
	
150
	function mdwp_add_p($text) {
151
		if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
152
			$text = '<p>'.$text.'</p>';
153
			$text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
154
		}
155
		return $text;
156
	}
157
	
158
	function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
159
160
	function mdwp_hide_tags($text) {
161
		global $mdwp_hidden_tags, $mdwp_placeholders;
162
		return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
163
	}
164
	function mdwp_show_tags($text) {
165
		global $mdwp_hidden_tags, $mdwp_placeholders;
166
		return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
167
	}
168
}
169
170
171
### bBlog Plugin Info ###
172
173
function identify_modifier_markdown() {
174
	return array(
175
		'name' => 'markdown',
176
		'type' => 'modifier',
177
		'nicename' => 'PHP Markdown Extra',
178
		'description' => 'A text-to-HTML conversion tool for web writers',
179
		'authors' => 'Michel Fortin and John Gruber',
180
		'licence' => 'GPL',
181
		'version' => MARKDOWNEXTRA_VERSION,
182
		'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.ca/projects/php-markdown/">More...</a>',
183
		);
184
}
185
186
187
### Smarty Modifier Interface ###
188
189
function smarty_modifier_markdown($text) {
190
	return Markdown($text);
191
}
192
193
194
### Textile Compatibility Mode ###
195
196
# Rename this file to "classTextile.php" and it can replace Textile everywhere.
197
198
if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
199
	# Try to include PHP SmartyPants. Should be in the same directory.
200
	@include_once 'smartypants.php';
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
201
	# Fake Textile class. It calls Markdown instead.
202
	class Textile {
203
		function TextileThis($text, $lite='', $encode='') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
204
			if ($lite == '' && $encode == '')    $text = Markdown($text);
205
			if (function_exists('SmartyPants'))  $text = SmartyPants($text);
206
			return $text;
207
		}
208
		# Fake restricted version: restrictions are not supported for now.
209
		function TextileRestricted($text, $lite='', $noimage='') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
210
			return $this->TextileThis($text, $lite);
211
		}
212
		# Workaround to ensure compatibility with TextPattern 4.0.3.
213
		function blockLite($text) { return $text; }
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
214
	}
215
}
216
217
218
219
#
220
# Markdown Parser Class
221
#
222
223
class Markdown_Parser {
224
225
	### Configuration Variables ###
226
227
	# Change to ">" for HTML output.
228
	var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
229
	var $tab_width = MARKDOWN_TAB_WIDTH;
230
	
231
	# Change to `true` to disallow markup or entities.
232
	var $no_markup = false;
233
	var $no_entities = false;
234
	
235
	# Predefined urls and titles for reference links and images.
236
	var $predef_urls = array();
237
	var $predef_titles = array();
238
239
240
	### Parser Implementation ###
241
242
	# Regex to match balanced [brackets].
243
	# Needed to insert a maximum bracked depth while converting to PHP.
244
	var $nested_brackets_depth = 6;
245
	var $nested_brackets_re;
246
	
247
	var $nested_url_parenthesis_depth = 4;
248
	var $nested_url_parenthesis_re;
249
250
	# Table of hash values for escaped characters:
251
	var $escape_chars = '\`*_{}[]()>#+-.!';
252
	var $escape_chars_re;
253
254
255
	function Markdown_Parser() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
256
	#
257
	# Constructor function. Initialize appropriate member variables.
258
	#
259
		$this->_initDetab();
260
		$this->prepareItalicsAndBold();
261
	
262
		$this->nested_brackets_re = 
263
			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
264
			str_repeat('\])*', $this->nested_brackets_depth);
265
	
266
		$this->nested_url_parenthesis_re = 
267
			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
268
			str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
269
		
270
		$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
271
		
272
		# Sort document, block, and span gamut in ascendent priority order.
273
		asort($this->document_gamut);
274
		asort($this->block_gamut);
275
		asort($this->span_gamut);
276
	}
277
278
279
	# Internal hashes used during transformation.
280
	var $urls = array();
281
	var $titles = array();
282
	var $html_hashes = array();
283
	
284
	# Status flag to avoid invalid nesting.
285
	var $in_anchor = false;
286
	
287
	
288
	function setup() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
289
	#
290
	# Called before the transformation process starts to setup parser 
291
	# states.
292
	#
293
		# Clear global hashes.
294
		$this->urls = $this->predef_urls;
295
		$this->titles = $this->predef_titles;
296
		$this->html_hashes = array();
297
		
298
		$this->in_anchor = false;
299
	}
300
	
301
	function teardown() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
302
	#
303
	# Called after the transformation process to clear any variable 
304
	# which may be taking up memory unnecessarly.
305
	#
306
		$this->urls = array();
307
		$this->titles = array();
308
		$this->html_hashes = array();
309
	}
310
311
312
	function transform($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
313
	#
314
	# Main function. Performs some preprocessing on the input text
315
	# and pass it through the document gamut.
316
	#
317
		$this->setup();
318
	
319
		# Remove UTF-8 BOM and marker character in input, if present.
320
		$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
321
322
		# Standardize line endings:
323
		#   DOS to Unix and Mac to Unix
324
		$text = preg_replace('{\r\n?}', "\n", $text);
325
326
		# Make sure $text ends with a couple of newlines:
327
		$text .= "\n\n";
328
329
		# Convert all tabs to spaces.
330
		$text = $this->detab($text);
331
332
		# Turn block-level HTML blocks into hash entries
333
		$text = $this->hashHTMLBlocks($text);
334
335
		# Strip any lines consisting only of spaces and tabs.
336
		# This makes subsequent regexen easier to write, because we can
337
		# match consecutive blank lines with /\n+/ instead of something
338
		# contorted like /[ ]*\n+/ .
339
		$text = preg_replace('/^[ ]+$/m', '', $text);
340
341
		# Run document gamut methods.
342
		foreach ($this->document_gamut as $method => $priority) {
343
			$text = $this->$method($text);
344
		}
345
		
346
		$this->teardown();
347
348
		return $text . "\n";
349
	}
350
	
351
	var $document_gamut = array(
352
		# Strip link definitions, store in hashes.
353
		"stripLinkDefinitions" => 20,
354
		
355
		"runBasicBlockGamut"   => 30,
356
		);
357
358
359 View Code Duplication
	function stripLinkDefinitions($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
	#
361
	# Strips link definitions from text, stores the URLs and titles in
362
	# hash references.
363
	#
364
		$less_than_tab = $this->tab_width - 1;
365
366
		# Link defs are in the form: ^[id]: url "optional title"
367
		$text = preg_replace_callback('{
368
							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
369
							  [ ]*
370
							  \n?				# maybe *one* newline
371
							  [ ]*
372
							(?:
373
							  <(.+?)>			# url = $2
374
							|
375
							  (\S+?)			# url = $3
376
							)
377
							  [ ]*
378
							  \n?				# maybe one newline
379
							  [ ]*
380
							(?:
381
								(?<=\s)			# lookbehind for whitespace
382
								["(]
383
								(.*?)			# title = $4
384
								[")]
385
								[ ]*
386
							)?	# title is optional
387
							(?:\n+|\Z)
388
			}xm',
389
			array(&$this, '_stripLinkDefinitions_callback'),
390
			$text);
391
		return $text;
392
	}
393
	function _stripLinkDefinitions_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
394
		$link_id = strtolower($matches[1]);
395
		$url = $matches[2] == '' ? $matches[3] : $matches[2];
396
		$this->urls[$link_id] = $url;
397
		$this->titles[$link_id] =& $matches[4];
398
		return ''; # String that will replace the block
399
	}
400
401
402
	function hashHTMLBlocks($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
403
		if ($this->no_markup)  return $text;
404
405
		$less_than_tab = $this->tab_width - 1;
406
407
		# Hashify HTML blocks:
408
		# We only want to do this for block-level HTML tags, such as headers,
409
		# lists, and tables. That's because we still want to wrap <p>s around
410
		# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
411
		# phrase emphasis, and spans. The list of tags we're looking for is
412
		# hard-coded:
413
		#
414
		# *  List "a" is made of tags which can be both inline or block-level.
415
		#    These will be treated block-level when the start tag is alone on 
416
		#    its line, otherwise they're not matched here and will be taken as 
417
		#    inline later.
418
		# *  List "b" is made of tags which are always block-level;
419
		#
420
		$block_tags_a_re = 'ins|del';
421
		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
422
						   'script|noscript|form|fieldset|iframe|math|svg|'.
423
						   'article|section|nav|aside|hgroup|header|footer|'.
424
						   'figure';
425
426
		# Regular expression for the content of a block tag.
427
		$nested_tags_level = 4;
428
		$attr = '
429
			(?>				# optional tag attributes
430
			  \s			# starts with whitespace
431
			  (?>
432
				[^>"/]+		# text outside quotes
433
			  |
434
				/+(?!>)		# slash not followed by ">"
435
			  |
436
				"[^"]*"		# text inside double quotes (tolerate ">")
437
			  |
438
				\'[^\']*\'	# text inside single quotes (tolerate ">")
439
			  )*
440
			)?	
441
			';
442
		$content =
443
			str_repeat('
444
				(?>
445
				  [^<]+			# content without tag
446
				|
447
				  <\2			# nested opening tag
448
					'.$attr.'	# attributes
449
					(?>
450
					  />
451
					|
452
					  >', $nested_tags_level).	# end of opening tag
453
					  '.*?'.					# last level nested tag content
454
			str_repeat('
455
					  </\2\s*>	# closing nested tag
456
					)
457
				  |				
458
					<(?!/\2\s*>	# other tags with a different name
459
				  )
460
				)*',
461
				$nested_tags_level);
462
		$content2 = str_replace('\2', '\3', $content);
463
464
		# First, look for nested blocks, e.g.:
465
		# 	<div>
466
		# 		<div>
467
		# 		tags for inner block must be indented.
468
		# 		</div>
469
		# 	</div>
470
		#
471
		# The outermost tags must start at the left margin for this to match, and
472
		# the inner nested divs must be indented.
473
		# We need to do this before the next, more liberal match, because the next
474
		# match will start at the first `<div>` and stop at the first `</div>`.
475
		$text = preg_replace_callback('{(?>
476
			(?>
477
				(?<=\n\n)		# Starting after a blank line
478
				|				# or
479
				\A\n?			# the beginning of the doc
480
			)
481
			(						# save in $1
482
483
			  # Match from `\n<tag>` to `</tag>\n`, handling nested tags 
484
			  # in between.
485
					
486
						[ ]{0,'.$less_than_tab.'}
487
						<('.$block_tags_b_re.')# start tag = $2
488
						'.$attr.'>			# attributes followed by > and \n
489
						'.$content.'		# content, support nesting
490
						</\2>				# the matching end tag
491
						[ ]*				# trailing spaces/tabs
492
						(?=\n+|\Z)	# followed by a newline or end of document
493
494
			| # Special version for tags of group a.
495
496
						[ ]{0,'.$less_than_tab.'}
497
						<('.$block_tags_a_re.')# start tag = $3
498
						'.$attr.'>[ ]*\n	# attributes followed by >
499
						'.$content2.'		# content, support nesting
500
						</\3>				# the matching end tag
501
						[ ]*				# trailing spaces/tabs
502
						(?=\n+|\Z)	# followed by a newline or end of document
503
					
504
			| # Special case just for <hr />. It was easier to make a special 
505
			  # case than to make the other regex more complicated.
506
			
507
						[ ]{0,'.$less_than_tab.'}
508
						<(hr)				# start tag = $2
509
						'.$attr.'			# attributes
510
						/?>					# the matching end tag
511
						[ ]*
512
						(?=\n{2,}|\Z)		# followed by a blank line or end of document
513
			
514
			| # Special case for standalone HTML comments:
515
			
516
					[ ]{0,'.$less_than_tab.'}
517
					(?s:
518
						<!-- .*? -->
519
					)
520
					[ ]*
521
					(?=\n{2,}|\Z)		# followed by a blank line or end of document
522
			
523
			| # PHP and ASP-style processor instructions (<? and <%)
524
			
525
					[ ]{0,'.$less_than_tab.'}
526
					(?s:
527
						<([?%])			# $2
528
						.*?
529
						\2>
530
					)
531
					[ ]*
532
					(?=\n{2,}|\Z)		# followed by a blank line or end of document
533
					
534
			)
535
			)}Sxmi',
536
			array(&$this, '_hashHTMLBlocks_callback'),
537
			$text);
538
539
		return $text;
540
	}
541
	function _hashHTMLBlocks_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
542
		$text = $matches[1];
543
		$key  = $this->hashBlock($text);
544
		return "\n\n$key\n\n";
545
	}
546
	
547
	
548
	function hashPart($text, $boundary = 'X') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
549
	#
550
	# Called whenever a tag must be hashed when a function insert an atomic 
551
	# element in the text stream. Passing $text to through this function gives
552
	# a unique text-token which will be reverted back when calling unhash.
553
	#
554
	# The $boundary argument specify what character should be used to surround
555
	# the token. By convension, "B" is used for block elements that needs not
556
	# to be wrapped into paragraph tags at the end, ":" is used for elements
557
	# that are word separators and "X" is used in the general case.
558
	#
559
		# Swap back any tag hash found in $text so we do not have to `unhash`
560
		# multiple times at the end.
561
		$text = $this->unhash($text);
562
		
563
		# Then hash the block.
564
		static $i = 0;
565
		$key = "$boundary\x1A" . ++$i . $boundary;
566
		$this->html_hashes[$key] = $text;
567
		return $key; # String that will replace the tag.
568
	}
569
570
571
	function hashBlock($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
572
	#
573
	# Shortcut function for hashPart with block-level boundaries.
574
	#
575
		return $this->hashPart($text, 'B');
576
	}
577
578
579
	var $block_gamut = array(
580
	#
581
	# These are all the transformations that form block-level
582
	# tags like paragraphs, headers, and list items.
583
	#
584
		"doHeaders"         => 10,
585
		"doHorizontalRules" => 20,
586
		
587
		"doLists"           => 40,
588
		"doCodeBlocks"      => 50,
589
		"doBlockQuotes"     => 60,
590
		);
591
592
	function runBlockGamut($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
593
	#
594
	# Run block gamut tranformations.
595
	#
596
		# We need to escape raw HTML in Markdown source before doing anything 
597
		# else. This need to be done for each block, and not only at the 
598
		# begining in the Markdown function since hashed blocks can be part of
599
		# list items and could have been indented. Indented blocks would have 
600
		# been seen as a code block in a previous pass of hashHTMLBlocks.
601
		$text = $this->hashHTMLBlocks($text);
602
		
603
		return $this->runBasicBlockGamut($text);
604
	}
605
	
606
	function runBasicBlockGamut($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
607
	#
608
	# Run block gamut tranformations, without hashing HTML blocks. This is 
609
	# useful when HTML blocks are known to be already hashed, like in the first
610
	# whole-document pass.
611
	#
612
		foreach ($this->block_gamut as $method => $priority) {
613
			$text = $this->$method($text);
614
		}
615
		
616
		# Finally form paragraph and restore hashed blocks.
617
		$text = $this->formParagraphs($text);
618
619
		return $text;
620
	}
621
	
622
	
623
	function doHorizontalRules($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
624
		# Do Horizontal Rules:
625
		return preg_replace(
626
			'{
627
				^[ ]{0,3}	# Leading space
628
				([-*_])		# $1: First marker
629
				(?>			# Repeated marker group
630
					[ ]{0,2}	# Zero, one, or two spaces.
631
					\1			# Marker character
632
				){2,}		# Group repeated at least twice
633
				[ ]*		# Tailing spaces
634
				$			# End of line.
635
			}mx',
636
			"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n", 
637
			$text);
638
	}
639
640
641
	var $span_gamut = array(
642
	#
643
	# These are all the transformations that occur *within* block-level
644
	# tags like paragraphs, headers, and list items.
645
	#
646
		# Process character escapes, code spans, and inline HTML
647
		# in one shot.
648
		"parseSpan"           => -30,
649
650
		# Process anchor and image tags. Images must come first,
651
		# because ![foo][f] looks like an anchor.
652
		"doImages"            =>  10,
653
		"doAnchors"           =>  20,
654
		
655
		# Make links out of things like `<http://example.com/>`
656
		# Must come after doAnchors, because you can use < and >
657
		# delimiters in inline links like [this](<url>).
658
		"doAutoLinks"         =>  30,
659
		"encodeAmpsAndAngles" =>  40,
660
661
		"doItalicsAndBold"    =>  50,
662
		"doHardBreaks"        =>  60,
663
		);
664
665
	function runSpanGamut($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
666
	#
667
	# Run span gamut tranformations.
668
	#
669
		foreach ($this->span_gamut as $method => $priority) {
670
			$text = $this->$method($text);
671
		}
672
673
		return $text;
674
	}
675
	
676
	
677
	function doHardBreaks($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
678
		# Do hard breaks:
679
		return preg_replace_callback('/ {2,}\n/', 
680
			array(&$this, '_doHardBreaks_callback'), $text);
681
	}
682
	function _doHardBreaks_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
683
		return $this->hashPart("<br$this->empty_element_suffix\n");
684
	}
685
686
687 View Code Duplication
	function doAnchors($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
688
	#
689
	# Turn Markdown link shortcuts into XHTML <a> tags.
690
	#
691
		if ($this->in_anchor) return $text;
692
		$this->in_anchor = true;
693
		
694
		#
695
		# First, handle reference-style links: [link text] [id]
696
		#
697
		$text = preg_replace_callback('{
698
			(					# wrap whole match in $1
699
			  \[
700
				('.$this->nested_brackets_re.')	# link text = $2
701
			  \]
702
703
			  [ ]?				# one optional space
704
			  (?:\n[ ]*)?		# one optional newline followed by spaces
705
706
			  \[
707
				(.*?)		# id = $3
708
			  \]
709
			)
710
			}xs',
711
			array(&$this, '_doAnchors_reference_callback'), $text);
712
713
		#
714
		# Next, inline-style links: [link text](url "optional title")
715
		#
716
		$text = preg_replace_callback('{
717
			(				# wrap whole match in $1
718
			  \[
719
				('.$this->nested_brackets_re.')	# link text = $2
720
			  \]
721
			  \(			# literal paren
722
				[ \n]*
723
				(?:
724
					<(.+?)>	# href = $3
725
				|
726
					('.$this->nested_url_parenthesis_re.')	# href = $4
727
				)
728
				[ \n]*
729
				(			# $5
730
				  ([\'"])	# quote char = $6
731
				  (.*?)		# Title = $7
732
				  \6		# matching quote
733
				  [ \n]*	# ignore any spaces/tabs between closing quote and )
734
				)?			# title is optional
735
			  \)
736
			)
737
			}xs',
738
			array(&$this, '_doAnchors_inline_callback'), $text);
739
740
		#
741
		# Last, handle reference-style shortcuts: [link text]
742
		# These must come last in case you've also got [link text][1]
743
		# or [link text](/foo)
744
		#
745
		$text = preg_replace_callback('{
746
			(					# wrap whole match in $1
747
			  \[
748
				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
749
			  \]
750
			)
751
			}xs',
752
			array(&$this, '_doAnchors_reference_callback'), $text);
753
754
		$this->in_anchor = false;
755
		return $text;
756
	}
757
	function _doAnchors_reference_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
758
		$whole_match =  $matches[1];
759
		$link_text   =  $matches[2];
760
		$link_id     =& $matches[3];
761
762
		if ($link_id == "") {
763
			# for shortcut links like [this][] or [this].
764
			$link_id = $link_text;
765
		}
766
		
767
		# lower-case and turn embedded newlines into spaces
768
		$link_id = strtolower($link_id);
769
		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
770
771
		if (isset($this->urls[$link_id])) {
772
			$url = $this->urls[$link_id];
773
			$url = $this->encodeAttribute($url);
774
			
775
			$result = "<a href=\"$url\"";
776 View Code Duplication
			if ( isset( $this->titles[$link_id] ) ) {
777
				$title = $this->titles[$link_id];
778
				$title = $this->encodeAttribute($title);
779
				$result .=  " title=\"$title\"";
780
			}
781
		
782
			$link_text = $this->runSpanGamut($link_text);
783
			$result .= ">$link_text</a>";
784
			$result = $this->hashPart($result);
785
		}
786
		else {
787
			$result = $whole_match;
788
		}
789
		return $result;
790
	}
791 View Code Duplication
	function _doAnchors_inline_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
792
		$whole_match	=  $matches[1];
0 ignored issues
show
Unused Code introduced by
$whole_match is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
793
		$link_text		=  $this->runSpanGamut($matches[2]);
794
		$url			=  $matches[3] == '' ? $matches[4] : $matches[3];
795
		$title			=& $matches[7];
796
797
		$url = $this->encodeAttribute($url);
798
799
		$result = "<a href=\"$url\"";
800
		if (isset($title)) {
801
			$title = $this->encodeAttribute($title);
802
			$result .=  " title=\"$title\"";
803
		}
804
		
805
		$link_text = $this->runSpanGamut($link_text);
806
		$result .= ">$link_text</a>";
807
808
		return $this->hashPart($result);
809
	}
810
811
812 View Code Duplication
	function doImages($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
813
	#
814
	# Turn Markdown image shortcuts into <img> tags.
815
	#
816
		#
817
		# First, handle reference-style labeled images: ![alt text][id]
818
		#
819
		$text = preg_replace_callback('{
820
			(				# wrap whole match in $1
821
			  !\[
822
				('.$this->nested_brackets_re.')		# alt text = $2
823
			  \]
824
825
			  [ ]?				# one optional space
826
			  (?:\n[ ]*)?		# one optional newline followed by spaces
827
828
			  \[
829
				(.*?)		# id = $3
830
			  \]
831
832
			)
833
			}xs', 
834
			array(&$this, '_doImages_reference_callback'), $text);
835
836
		#
837
		# Next, handle inline images:  ![alt text](url "optional title")
838
		# Don't forget: encode * and _
839
		#
840
		$text = preg_replace_callback('{
841
			(				# wrap whole match in $1
842
			  !\[
843
				('.$this->nested_brackets_re.')		# alt text = $2
844
			  \]
845
			  \s?			# One optional whitespace character
846
			  \(			# literal paren
847
				[ \n]*
848
				(?:
849
					<(\S*)>	# src url = $3
850
				|
851
					('.$this->nested_url_parenthesis_re.')	# src url = $4
852
				)
853
				[ \n]*
854
				(			# $5
855
				  ([\'"])	# quote char = $6
856
				  (.*?)		# title = $7
857
				  \6		# matching quote
858
				  [ \n]*
859
				)?			# title is optional
860
			  \)
861
			)
862
			}xs',
863
			array(&$this, '_doImages_inline_callback'), $text);
864
865
		return $text;
866
	}
867
	function _doImages_reference_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
868
		$whole_match = $matches[1];
869
		$alt_text    = $matches[2];
870
		$link_id     = strtolower($matches[3]);
871
872
		if ($link_id == "") {
873
			$link_id = strtolower($alt_text); # for shortcut links like ![this][].
874
		}
875
876
		$alt_text = $this->encodeAttribute($alt_text);
877
		if (isset($this->urls[$link_id])) {
878
			$url = $this->encodeAttribute($this->urls[$link_id]);
879
			$result = "<img src=\"$url\" alt=\"$alt_text\"";
880 View Code Duplication
			if (isset($this->titles[$link_id])) {
881
				$title = $this->titles[$link_id];
882
				$title = $this->encodeAttribute($title);
883
				$result .=  " title=\"$title\"";
884
			}
885
			$result .= $this->empty_element_suffix;
886
			$result = $this->hashPart($result);
887
		}
888
		else {
889
			# If there's no such link ID, leave intact:
890
			$result = $whole_match;
891
		}
892
893
		return $result;
894
	}
895 View Code Duplication
	function _doImages_inline_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
896
		$whole_match	= $matches[1];
0 ignored issues
show
Unused Code introduced by
$whole_match is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
897
		$alt_text		= $matches[2];
898
		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
899
		$title			=& $matches[7];
900
901
		$alt_text = $this->encodeAttribute($alt_text);
902
		$url = $this->encodeAttribute($url);
903
		$result = "<img src=\"$url\" alt=\"$alt_text\"";
904
		if (isset($title)) {
905
			$title = $this->encodeAttribute($title);
906
			$result .=  " title=\"$title\""; # $title already quoted
907
		}
908
		$result .= $this->empty_element_suffix;
909
910
		return $this->hashPart($result);
911
	}
912
913
914
	function doHeaders($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
915
		# Setext-style headers:
916
		#	  Header 1
917
		#	  ========
918
		#  
919
		#	  Header 2
920
		#	  --------
921
		#
922
		$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
923
			array(&$this, '_doHeaders_callback_setext'), $text);
924
925
		# atx-style headers:
926
		#	# Header 1
927
		#	## Header 2
928
		#	## Header 2 with closing hashes ##
929
		#	...
930
		#	###### Header 6
931
		#
932
		$text = preg_replace_callback('{
933
				^(\#{1,6})	# $1 = string of #\'s
934
				[ ]*
935
				(.+?)		# $2 = Header text
936
				[ ]*
937
				\#*			# optional closing #\'s (not counted)
938
				\n+
939
			}xm',
940
			array(&$this, '_doHeaders_callback_atx'), $text);
941
942
		return $text;
943
	}
944
	function _doHeaders_callback_setext($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
945
		# Terrible hack to check we haven't found an empty list item.
946 View Code Duplication
		if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
947
			return $matches[0];
948
		
949
		$level = $matches[2]{0} == '=' ? 1 : 2;
950
		$block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
951
		return "\n" . $this->hashBlock($block) . "\n\n";
952
	}
953
	function _doHeaders_callback_atx($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
954
		$level = strlen($matches[1]);
955
		$block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
956
		return "\n" . $this->hashBlock($block) . "\n\n";
957
	}
958
959
960
	function doLists($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
961
	#
962
	# Form HTML ordered (numbered) and unordered (bulleted) lists.
963
	#
964
		$less_than_tab = $this->tab_width - 1;
965
966
		# Re-usable patterns to match list item bullets and number markers:
967
		$marker_ul_re  = '[*+-]';
968
		$marker_ol_re  = '\d+[\.]';
969
		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
0 ignored issues
show
Unused Code introduced by
$marker_any_re is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
970
971
		$markers_relist = array(
972
			$marker_ul_re => $marker_ol_re,
973
			$marker_ol_re => $marker_ul_re,
974
			);
975
976
		foreach ($markers_relist as $marker_re => $other_marker_re) {
977
			# Re-usable pattern to match any entirel ul or ol list:
978
			$whole_list_re = '
979
				(								# $1 = whole list
980
				  (								# $2
981
					([ ]{0,'.$less_than_tab.'})	# $3 = number of spaces
982
					('.$marker_re.')			# $4 = first list item marker
983
					[ ]+
984
				  )
985
				  (?s:.+?)
986
				  (								# $5
987
					  \z
988
					|
989
					  \n{2,}
990
					  (?=\S)
991
					  (?!						# Negative lookahead for another list item marker
992
						[ ]*
993
						'.$marker_re.'[ ]+
994
					  )
995
					|
996
					  (?=						# Lookahead for another kind of list
997
					    \n
998
						\3						# Must have the same indentation
999
						'.$other_marker_re.'[ ]+
1000
					  )
1001
				  )
1002
				)
1003
			'; // mx
1004
			
1005
			# We use a different prefix before nested lists than top-level lists.
1006
			# See extended comment in _ProcessListItems().
1007
		
1008
			if ($this->list_level) {
1009
				$text = preg_replace_callback('{
1010
						^
1011
						'.$whole_list_re.'
1012
					}mx',
1013
					array(&$this, '_doLists_callback'), $text);
1014
			}
1015
			else {
1016
				$text = preg_replace_callback('{
1017
						(?:(?<=\n)\n|\A\n?) # Must eat the newline
1018
						'.$whole_list_re.'
1019
					}mx',
1020
					array(&$this, '_doLists_callback'), $text);
1021
			}
1022
		}
1023
1024
		return $text;
1025
	}
1026
	function _doLists_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1027
		# Re-usable patterns to match list item bullets and number markers:
1028
		$marker_ul_re  = '[*+-]';
1029
		$marker_ol_re  = '\d+[\.]';
1030
		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
0 ignored issues
show
Unused Code introduced by
$marker_any_re is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1031
		
1032
		$list = $matches[1];
1033
		$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
1034
		
1035
		$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
1036
		
1037
		$list .= "\n";
1038
		$result = $this->processListItems($list, $marker_any_re);
1039
		
1040
		$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
1041
		return "\n". $result ."\n\n";
1042
	}
1043
1044
	var $list_level = 0;
1045
1046
	function processListItems($list_str, $marker_any_re) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1047
	#
1048
	#	Process the contents of a single ordered or unordered list, splitting it
1049
	#	into individual list items.
1050
	#
1051
		# The $this->list_level global keeps track of when we're inside a list.
1052
		# Each time we enter a list, we increment it; when we leave a list,
1053
		# we decrement. If it's zero, we're not in a list anymore.
1054
		#
1055
		# We do this because when we're not inside a list, we want to treat
1056
		# something like this:
1057
		#
1058
		#		I recommend upgrading to version
1059
		#		8. Oops, now this line is treated
1060
		#		as a sub-list.
1061
		#
1062
		# As a single paragraph, despite the fact that the second line starts
1063
		# with a digit-period-space sequence.
1064
		#
1065
		# Whereas when we're inside a list (or sub-list), that line will be
1066
		# treated as the start of a sub-list. What a kludge, huh? This is
1067
		# an aspect of Markdown's syntax that's hard to parse perfectly
1068
		# without resorting to mind-reading. Perhaps the solution is to
1069
		# change the syntax rules such that sub-lists must start with a
1070
		# starting cardinal number; e.g. "1." or "a.".
1071
		
1072
		$this->list_level++;
1073
1074
		# trim trailing blank lines:
1075
		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1076
1077
		$list_str = preg_replace_callback('{
1078
			(\n)?							# leading line = $1
1079
			(^[ ]*)							# leading whitespace = $2
1080
			('.$marker_any_re.'				# list marker and space = $3
1081
				(?:[ ]+|(?=\n))	# space only required if item is not empty
1082
			)
1083
			((?s:.*?))						# list item text   = $4
1084
			(?:(\n+(?=\n))|\n)				# tailing blank line = $5
1085
			(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
1086
			}xm',
1087
			array(&$this, '_processListItems_callback'), $list_str);
1088
1089
		$this->list_level--;
1090
		return $list_str;
1091
	}
1092
	function _processListItems_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1093
		$item = $matches[4];
1094
		$leading_line =& $matches[1];
1095
		$leading_space =& $matches[2];
1096
		$marker_space = $matches[3];
1097
		$tailing_blank_line =& $matches[5];
1098
1099 View Code Duplication
		if ($leading_line || $tailing_blank_line || 
1100
			preg_match('/\n{2,}/', $item))
1101
		{
1102
			# Replace marker with the appropriate whitespace indentation
1103
			$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
1104
			$item = $this->runBlockGamut($this->outdent($item)."\n");
1105
		}
1106
		else {
1107
			# Recursion for sub-lists:
1108
			$item = $this->doLists($this->outdent($item));
1109
			$item = preg_replace('/\n+$/', '', $item);
1110
			$item = $this->runSpanGamut($item);
1111
		}
1112
1113
		return "<li>" . $item . "</li>\n";
1114
	}
1115
1116
1117
	function doCodeBlocks($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1118
	#
1119
	#	Process Markdown `<pre><code>` blocks.
1120
	#
1121
		$text = preg_replace_callback('{
1122
				(?:\n\n|\A\n?)
1123
				(	            # $1 = the code block -- one or more lines, starting with a space/tab
1124
				  (?>
1125
					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
1126
					.*\n+
1127
				  )+
1128
				)
1129
				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
1130
			}xm',
1131
			array(&$this, '_doCodeBlocks_callback'), $text);
1132
1133
		return $text;
1134
	}
1135
	function _doCodeBlocks_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1136
		$codeblock = $matches[1];
1137
1138
		$codeblock = $this->outdent($codeblock);
1139
		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1140
1141
		# trim leading newlines and trailing newlines
1142
		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
1143
1144
		$codeblock = "<pre><code>$codeblock\n</code></pre>";
1145
		return "\n\n".$this->hashBlock($codeblock)."\n\n";
1146
	}
1147
1148
1149
	function makeCodeSpan($code) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1150
	#
1151
	# Create a code span markup for $code. Called from handleSpanToken.
1152
	#
1153
		$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
1154
		return $this->hashPart("<code>$code</code>");
1155
	}
1156
1157
1158
	var $em_relist = array(
1159
		''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S|$)(?![\.,:;]\s)',
1160
		'*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
1161
		'_' => '(?<=\S|^)(?<!_)_(?!_)',
1162
		);
1163
	var $strong_relist = array(
1164
		''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S|$)(?![\.,:;]\s)',
1165
		'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
1166
		'__' => '(?<=\S|^)(?<!_)__(?!_)',
1167
		);
1168
	var $em_strong_relist = array(
1169
		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S|$)(?![\.,:;]\s)',
1170
		'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
1171
		'___' => '(?<=\S|^)(?<!_)___(?!_)',
1172
		);
1173
	var $em_strong_prepared_relist;
1174
	
1175
	function prepareItalicsAndBold() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1176
	#
1177
	# Prepare regular expressions for searching emphasis tokens in any
1178
	# context.
1179
	#
1180
		foreach ($this->em_relist as $em => $em_re) {
1181
			foreach ($this->strong_relist as $strong => $strong_re) {
1182
				# Construct list of allowed token expressions.
1183
				$token_relist = array();
1184
				if (isset($this->em_strong_relist["$em$strong"])) {
1185
					$token_relist[] = $this->em_strong_relist["$em$strong"];
1186
				}
1187
				$token_relist[] = $em_re;
1188
				$token_relist[] = $strong_re;
1189
				
1190
				# Construct master expression from list.
1191
				$token_re = '{('. implode('|', $token_relist) .')}';
1192
				$this->em_strong_prepared_relist["$em$strong"] = $token_re;
1193
			}
1194
		}
1195
	}
1196
	
1197
	function doItalicsAndBold($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1198
		$token_stack = array('');
1199
		$text_stack = array('');
1200
		$em = '';
1201
		$strong = '';
1202
		$tree_char_em = false;
1203
		
1204
		while (1) {
1205
			#
1206
			# Get prepared regular expression for seraching emphasis tokens
1207
			# in current context.
1208
			#
1209
			$token_re = $this->em_strong_prepared_relist["$em$strong"];
1210
			
1211
			#
1212
			# Each loop iteration search for the next emphasis token. 
1213
			# Each token is then passed to handleSpanToken.
1214
			#
1215
			$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1216
			$text_stack[0] .= $parts[0];
1217
			$token =& $parts[1];
1218
			$text =& $parts[2];
1219
			
1220 View Code Duplication
			if (empty($token)) {
1221
				# Reached end of text span: empty stack without emitting.
1222
				# any more emphasis.
1223
				while ($token_stack[0]) {
1224
					$text_stack[1] .= array_shift($token_stack);
1225
					$text_stack[0] .= array_shift($text_stack);
1226
				}
1227
				break;
1228
			}
1229
			
1230
			$token_len = strlen($token);
1231
			if ($tree_char_em) {
1232
				# Reached closing marker while inside a three-char emphasis.
1233
				if ($token_len == 3) {
1234
					# Three-char closing marker, close em and strong.
1235
					array_shift($token_stack);
1236
					$span = array_shift($text_stack);
1237
					$span = $this->runSpanGamut($span);
1238
					$span = "<strong><em>$span</em></strong>";
1239
					$text_stack[0] .= $this->hashPart($span);
1240
					$em = '';
1241
					$strong = '';
1242
				} else {
1243
					# Other closing marker: close one em or strong and
1244
					# change current token state to match the other
1245
					$token_stack[0] = str_repeat($token{0}, 3-$token_len);
1246
					$tag = $token_len == 2 ? "strong" : "em";
1247
					$span = $text_stack[0];
1248
					$span = $this->runSpanGamut($span);
1249
					$span = "<$tag>$span</$tag>";
1250
					$text_stack[0] = $this->hashPart($span);
1251
					$$tag = ''; # $$tag stands for $em or $strong
1252
				}
1253
				$tree_char_em = false;
1254
			} else if ($token_len == 3) {
1255
				if ($em) {
1256
					# Reached closing marker for both em and strong.
1257
					# Closing strong marker:
1258
					for ($i = 0; $i < 2; ++$i) {
1259
						$shifted_token = array_shift($token_stack);
1260
						$tag = strlen($shifted_token) == 2 ? "strong" : "em";
1261
						$span = array_shift($text_stack);
1262
						$span = $this->runSpanGamut($span);
1263
						$span = "<$tag>$span</$tag>";
1264
						$text_stack[0] .= $this->hashPart($span);
1265
						$$tag = ''; # $$tag stands for $em or $strong
1266
					}
1267
				} else {
1268
					# Reached opening three-char emphasis marker. Push on token 
1269
					# stack; will be handled by the special condition above.
1270
					$em = $token{0};
1271
					$strong = "$em$em";
1272
					array_unshift($token_stack, $token);
1273
					array_unshift($text_stack, '');
1274
					$tree_char_em = true;
1275
				}
1276
			} else if ($token_len == 2) {
1277
				if ($strong) {
1278
					# Unwind any dangling emphasis marker:
1279 View Code Duplication
					if (strlen($token_stack[0]) == 1) {
1280
						$text_stack[1] .= array_shift($token_stack);
1281
						$text_stack[0] .= array_shift($text_stack);
1282
					}
1283
					# Closing strong marker:
1284
					array_shift($token_stack);
1285
					$span = array_shift($text_stack);
1286
					$span = $this->runSpanGamut($span);
1287
					$span = "<strong>$span</strong>";
1288
					$text_stack[0] .= $this->hashPart($span);
1289
					$strong = '';
1290
				} else {
1291
					array_unshift($token_stack, $token);
1292
					array_unshift($text_stack, '');
1293
					$strong = $token;
1294
				}
1295
			} else {
1296
				# Here $token_len == 1
1297
				if ($em) {
1298
					if (strlen($token_stack[0]) == 1) {
1299
						# Closing emphasis marker:
1300
						array_shift($token_stack);
1301
						$span = array_shift($text_stack);
1302
						$span = $this->runSpanGamut($span);
1303
						$span = "<em>$span</em>";
1304
						$text_stack[0] .= $this->hashPart($span);
1305
						$em = '';
1306
					} else {
1307
						$text_stack[0] .= $token;
1308
					}
1309
				} else {
1310
					array_unshift($token_stack, $token);
1311
					array_unshift($text_stack, '');
1312
					$em = $token;
1313
				}
1314
			}
1315
		}
1316
		return $text_stack[0];
1317
	}
1318
1319
1320
	function doBlockQuotes($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1321
		$text = preg_replace_callback('/
1322
			  (								# Wrap whole match in $1
1323
				(?>
1324
				  ^[ ]*>[ ]?			# ">" at the start of a line
1325
					.+\n					# rest of the first line
1326
				  (.+\n)*					# subsequent consecutive lines
1327
				  \n*						# blanks
1328
				)+
1329
			  )
1330
			/xm',
1331
			array(&$this, '_doBlockQuotes_callback'), $text);
1332
1333
		return $text;
1334
	}
1335
	function _doBlockQuotes_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1336
		$bq = $matches[1];
1337
		# trim one level of quoting - trim whitespace-only lines
1338
		$bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1339
		$bq = $this->runBlockGamut($bq);		# recurse
1340
1341
		$bq = preg_replace('/^/m', "  ", $bq);
1342
		# These leading spaces cause problem with <pre> content, 
1343
		# so we need to fix that:
1344
		$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', 
1345
			array(&$this, '_doBlockQuotes_callback2'), $bq);
1346
1347
		return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
1348
	}
1349
	function _doBlockQuotes_callback2($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1350
		$pre = $matches[1];
1351
		$pre = preg_replace('/^  /m', '', $pre);
1352
		return $pre;
1353
	}
1354
1355
1356
	function formParagraphs($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1357
	#
1358
	#	Params:
1359
	#		$text - string to process with html <p> tags
1360
	#
1361
		# Strip leading and trailing lines:
1362
		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
1363
1364
		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1365
1366
		#
1367
		# Wrap <p> tags and unhashify HTML blocks
1368
		#
1369
		foreach ($grafs as $key => $value) {
1370
			if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1371
				# Is a paragraph.
1372
				$value = $this->runSpanGamut($value);
1373
				$value = preg_replace('/^([ ]*)/', "<p>", $value);
1374
				$value .= "</p>";
1375
				$grafs[$key] = $this->unhash($value);
1376
			}
1377
			else {
1378
				# Is a block.
1379
				# Modify elements of @grafs in-place...
1380
				$graf = $value;
1381
				$block = $this->html_hashes[$graf];
1382
				$graf = $block;
1383
//				if (preg_match('{
1384
//					\A
1385
//					(							# $1 = <div> tag
1386
//					  <div  \s+
1387
//					  [^>]*
1388
//					  \b
1389
//					  markdown\s*=\s*  ([\'"])	#	$2 = attr quote char
1390
//					  1
1391
//					  \2
1392
//					  [^>]*
1393
//					  >
1394
//					)
1395
//					(							# $3 = contents
1396
//					.*
1397
//					)
1398
//					(</div>)					# $4 = closing tag
1399
//					\z
1400
//					}xs', $block, $matches))
1401
//				{
1402
//					list(, $div_open, , $div_content, $div_close) = $matches;
1403
//
1404
//					# We can't call Markdown(), because that resets the hash;
1405
//					# that initialization code should be pulled into its own sub, though.
1406
//					$div_content = $this->hashHTMLBlocks($div_content);
1407
//					
1408
//					# Run document gamut methods on the content.
1409
//					foreach ($this->document_gamut as $method => $priority) {
1410
//						$div_content = $this->$method($div_content);
1411
//					}
1412
//
1413
//					$div_open = preg_replace(
1414
//						'{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
1415
//
1416
//					$graf = $div_open . "\n" . $div_content . "\n" . $div_close;
1417
//				}
1418
				$grafs[$key] = $graf;
1419
			}
1420
		}
1421
1422
		return implode("\n\n", $grafs);
1423
	}
1424
1425
1426
	function encodeAttribute($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1427
	#
1428
	# Encode text for a double-quoted HTML attribute. This function
1429
	# is *not* suitable for attributes enclosed in single quotes.
1430
	#
1431
		$text = $this->encodeAmpsAndAngles($text);
1432
		$text = str_replace('"', '&quot;', $text);
1433
		return $text;
1434
	}
1435
	
1436
	
1437
	function encodeAmpsAndAngles($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1438
	#
1439
	# Smart processing for ampersands and angle brackets that need to 
1440
	# be encoded. Valid character entities are left alone unless the
1441
	# no-entities mode is set.
1442
	#
1443
		if ($this->no_entities) {
1444
			$text = str_replace('&', '&amp;', $text);
1445
		} else {
1446
			# Ampersand-encoding based entirely on Nat Irons's Amputator
1447
			# MT plugin: <http://bumppo.net/projects/amputator/>
1448
			$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
1449
								'&amp;', $text);;
1450
		}
1451
		# Encode remaining <'s
1452
		$text = str_replace('<', '&lt;', $text);
1453
1454
		return $text;
1455
	}
1456
1457
1458
	function doAutoLinks($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1459
		$text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', 
1460
			array(&$this, '_doAutoLinks_url_callback'), $text);
1461
1462
		# Email addresses: <[email protected]>
1463
		$text = preg_replace_callback('{
1464
			<
1465
			(?:mailto:)?
1466
			(
1467
				(?:
1468
					[-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
1469
				|
1470
					".*?"
1471
				)
1472
				\@
1473
				(?:
1474
					[-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
1475
				|
1476
					\[[\d.a-fA-F:]+\]	# IPv4 & IPv6
1477
				)
1478
			)
1479
			>
1480
			}xi',
1481
			array(&$this, '_doAutoLinks_email_callback'), $text);
1482
		$text = preg_replace_callback('{<(tel:([^\'">\s]+))>}i',array(&$this, '_doAutoLinks_tel_callback'), $text);
1483
1484
		return $text;
1485
	}
1486
	function _doAutoLinks_tel_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1487
		$url = $this->encodeAttribute($matches[1]);
1488
		$tel = $this->encodeAttribute($matches[2]);
1489
		$link = "<a href=\"$url\">$tel</a>";
1490
		return $this->hashPart($link);
1491
	}
1492
	function _doAutoLinks_url_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1493
		$url = $this->encodeAttribute($matches[1]);
1494
		$link = "<a href=\"$url\">$url</a>";
1495
		return $this->hashPart($link);
1496
	}
1497
	function _doAutoLinks_email_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1498
		$address = $matches[1];
1499
		$link = $this->encodeEmailAddress($address);
1500
		return $this->hashPart($link);
1501
	}
1502
1503
1504
	function encodeEmailAddress($addr) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1505
	#
1506
	#	Input: an email address, e.g. "[email protected]"
1507
	#
1508
	#	Output: the email address as a mailto link, with each character
1509
	#		of the address encoded as either a decimal or hex entity, in
1510
	#		the hopes of foiling most address harvesting spam bots. E.g.:
1511
	#
1512
	#	  <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1513
	#        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1514
	#        &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
1515
	#        &#101;&#46;&#x63;&#111;&#x6d;</a></p>
1516
	#
1517
	#	Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1518
	#   With some optimizations by Milian Wolff.
1519
	#
1520
		$addr = "mailto:" . $addr;
1521
		$chars = preg_split('/(?<!^)(?!$)/', $addr);
1522
		$seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
1523
		
1524
		foreach ($chars as $key => $char) {
1525
			$ord = ord($char);
1526
			# Ignore non-ascii chars.
1527
			if ($ord < 128) {
1528
				$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
1529
				# roughly 10% raw, 45% hex, 45% dec
1530
				# '@' *must* be encoded. I insist.
1531
				if ($r > 90 && $char != '@') /* do nothing */;
1532
				else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
1533
				else              $chars[$key] = '&#'.$ord.';';
1534
			}
1535
		}
1536
		
1537
		$addr = implode('', $chars);
1538
		$text = implode('', array_slice($chars, 7)); # text without `mailto:`
1539
		$addr = "<a href=\"$addr\">$text</a>";
1540
1541
		return $addr;
1542
	}
1543
1544
1545
	function parseSpan($str) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1546
	#
1547
	# Take the string $str and parse it into tokens, hashing embeded HTML,
1548
	# escaped characters and handling code spans.
1549
	#
1550
		$output = '';
1551
		
1552
		$span_re = '{
1553
				(
1554
					\\\\'.$this->escape_chars_re.'
1555
				|
1556
					(?<![`\\\\])
1557
					`+						# code span marker
1558
			'.( $this->no_markup ? '' : '
1559
				|
1560
					<!--    .*?     -->		# comment
1561
				|
1562
					<\?.*?\?> | <%.*?%>		# processing instruction
1563
				|
1564
					<[!$]?[-a-zA-Z0-9:_]+	# regular tags
1565
					(?>
1566
						\s
1567
						(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
1568
					)?
1569
					>
1570
				|
1571
					<[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag
1572
				|
1573
					</[-a-zA-Z0-9:_]+\s*> # closing tag
1574
			').'
1575
				)
1576
				}xs';
1577
1578
		while (1) {
1579
			#
1580
			# Each loop iteration seach for either the next tag, the next 
1581
			# openning code span marker, or the next escaped character. 
1582
			# Each token is then passed to handleSpanToken.
1583
			#
1584
			$parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1585
			
1586
			# Create token from text preceding tag.
1587
			if ($parts[0] != "") {
1588
				$output .= $parts[0];
1589
			}
1590
			
1591
			# Check if we reach the end.
1592
			if (isset($parts[1])) {
1593
				$output .= $this->handleSpanToken($parts[1], $parts[2]);
1594
				$str = $parts[2];
1595
			}
1596
			else {
1597
				break;
1598
			}
1599
		}
1600
		
1601
		return $output;
1602
	}
1603
	
1604
	
1605
	function handleSpanToken($token, &$str) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1606
	#
1607
	# Handle $token provided by parseSpan by determining its nature and 
1608
	# returning the corresponding value that should replace it.
1609
	#
1610
		switch ($token{0}) {
1611
			case "\\":
1612
				return $this->hashPart("&#". ord($token{1}). ";");
1613
			case "`":
1614
				# Search for end marker in remaining text.
1615
				if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', 
1616
					$str, $matches))
1617
				{
1618
					$str = $matches[2];
1619
					$codespan = $this->makeCodeSpan($matches[1]);
1620
					return $this->hashPart($codespan);
1621
				}
1622
				return $token; // return as text since no ending marker found.
1623
			default:
1624
				return $this->hashPart($token);
1625
		}
1626
	}
1627
1628
1629
	function outdent($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1630
	#
1631
	# Remove one level of line-leading tabs or spaces
1632
	#
1633
		return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
1634
	}
1635
1636
1637
	# String length function for detab. `_initDetab` will create a function to 
1638
	# hanlde UTF-8 if the default function does not exist.
1639
	var $utf8_strlen = 'mb_strlen';
1640
	
1641
	function detab($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1642
	#
1643
	# Replace tabs with the appropriate amount of space.
1644
	#
1645
		# For each line we separate the line in blocks delemited by
1646
		# tab characters. Then we reconstruct every line by adding the 
1647
		# appropriate number of space between each blocks.
1648
		
1649
		$text = preg_replace_callback('/^.*\t.*$/m',
1650
			array(&$this, '_detab_callback'), $text);
1651
1652
		return $text;
1653
	}
1654
	function _detab_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1655
		$line = $matches[0];
1656
		$strlen = $this->utf8_strlen; # strlen function for UTF-8.
1657
		
1658
		# Split in blocks.
1659
		$blocks = explode("\t", $line);
1660
		# Add each blocks to the line.
1661
		$line = $blocks[0];
1662
		unset($blocks[0]); # Do not add first block twice.
1663
		foreach ($blocks as $block) {
1664
			# Calculate amount of space, insert spaces, insert block.
1665
			$amount = $this->tab_width - 
1666
				$strlen($line, 'UTF-8') % $this->tab_width;
1667
			$line .= str_repeat(" ", $amount) . $block;
1668
		}
1669
		return $line;
1670
	}
1671
	function _initDetab() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1672
	#
1673
	# Check for the availability of the function in the `utf8_strlen` property
1674
	# (initially `mb_strlen`). If the function is not available, create a 
1675
	# function that will loosely count the number of UTF-8 characters with a
1676
	# regular expression.
1677
	#
1678
		if (function_exists($this->utf8_strlen)) return;
1679
		$this->utf8_strlen = create_function('$text', 'return preg_match_all(
1680
			"/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", 
1681
			$text, $m);');
1682
	}
1683
1684
1685
	function unhash($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1686
	#
1687
	# Swap back in all the tags hashed by _HashHTMLBlocks.
1688
	#
1689
		return preg_replace_callback('/(.)\x1A[0-9]+\1/', 
1690
			array(&$this, '_unhash_callback'), $text);
1691
	}
1692
	function _unhash_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1693
		return $this->html_hashes[$matches[0]];
1694
	}
1695
1696
}
1697
1698
1699
#
1700
# Markdown Extra Parser Class
1701
#
1702
1703
class MarkdownExtra_Parser extends Markdown_Parser {
1704
1705
	### Configuration Variables ###
1706
1707
	# Prefix for footnote ids.
1708
	var $fn_id_prefix = "";
1709
	
1710
	# Optional title attribute for footnote links and backlinks.
1711
	var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
1712
	var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
1713
	
1714
	# Optional class attribute for footnote links and backlinks.
1715
	var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
1716
	var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
1717
1718
	# Optional class prefix for fenced code block.
1719
	var $code_class_prefix = MARKDOWN_CODE_CLASS_PREFIX;
1720
	# Class attribute for code blocks goes on the `code` tag;
1721
	# setting this to true will put attributes on the `pre` tag instead.
1722
	var $code_attr_on_pre = MARKDOWN_CODE_ATTR_ON_PRE;
1723
	
1724
	# Predefined abbreviations.
1725
	var $predef_abbr = array();
1726
1727
1728
	### Parser Implementation ###
1729
1730
	function MarkdownExtra_Parser() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1731
	#
1732
	# Constructor function. Initialize the parser object.
1733
	#
1734
		# Add extra escapable characters before parent constructor 
1735
		# initialize the table.
1736
		$this->escape_chars .= ':|';
1737
		
1738
		# Insert extra document, block, and span transformations. 
1739
		# Parent constructor will do the sorting.
1740
		$this->document_gamut += array(
1741
			"doFencedCodeBlocks" => 5,
1742
			"stripFootnotes"     => 15,
1743
			"stripAbbreviations" => 25,
1744
			"appendFootnotes"    => 50,
1745
			);
1746
		$this->block_gamut += array(
1747
			"doFencedCodeBlocks" => 5,
1748
			"doTables"           => 15,
1749
			"doDefLists"         => 45,
1750
			);
1751
		$this->span_gamut += array(
1752
			"doFootnotes"        => 5,
1753
			"doAbbreviations"    => 70,
1754
			);
1755
		
1756
		parent::Markdown_Parser();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (Markdown_Parser() instead of MarkdownExtra_Parser()). Are you sure this is correct? If so, you might want to change this to $this->Markdown_Parser().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
1757
	}
1758
	
1759
	
1760
	# Extra variables used during extra transformations.
1761
	var $footnotes = array();
1762
	var $footnotes_ordered = array();
1763
	var $footnotes_ref_count = array();
1764
	var $footnotes_numbers = array();
1765
	var $abbr_desciptions = array();
1766
	var $abbr_word_re = '';
1767
	
1768
	# Give the current footnote number.
1769
	var $footnote_counter = 1;
1770
	
1771
	
1772
	function setup() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1773
	#
1774
	# Setting up Extra-specific variables.
1775
	#
1776
		parent::setup();
1777
		
1778
		$this->footnotes = array();
1779
		$this->footnotes_ordered = array();
1780
		$this->footnotes_ref_count = array();
1781
		$this->footnotes_numbers = array();
1782
		$this->abbr_desciptions = array();
1783
		$this->abbr_word_re = '';
1784
		$this->footnote_counter = 1;
1785
		
1786
		foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
1787
			if ($this->abbr_word_re)
1788
				$this->abbr_word_re .= '|';
1789
			$this->abbr_word_re .= preg_quote($abbr_word);
1790
			$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
1791
		}
1792
	}
1793
	
1794
	function teardown() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1795
	#
1796
	# Clearing Extra-specific variables.
1797
	#
1798
		$this->footnotes = array();
1799
		$this->footnotes_ordered = array();
1800
		$this->footnotes_ref_count = array();
1801
		$this->footnotes_numbers = array();
1802
		$this->abbr_desciptions = array();
1803
		$this->abbr_word_re = '';
1804
		
1805
		parent::teardown();
1806
	}
1807
	
1808
	
1809
	### Extra Attribute Parser ###
1810
1811
	# Expression to use to catch attributes (includes the braces)
1812
	var $id_class_attr_catch_re = '\{((?:[ ]*[#.][-_:a-zA-Z0-9]+){1,})[ ]*\}';
1813
	# Expression to use when parsing in a context when no capture is desired
1814
	var $id_class_attr_nocatch_re = '\{(?:[ ]*[#.][-_:a-zA-Z0-9]+){1,}[ ]*\}';
1815
1816
	function doExtraAttributes($tag_name, $attr) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1817
	#
1818
	# Parse attributes caught by the $this->id_class_attr_catch_re expression
1819
	# and return the HTML-formatted list of attributes.
1820
	#
1821
	# Currently supported attributes are .class and #id.
1822
	#
1823
		if (empty($attr)) return "";
1824
		
1825
		# Split on components
1826
		preg_match_all('/[#.][-_:a-zA-Z0-9]+/', $attr, $matches);
1827
		$elements = $matches[0];
1828
1829
		# handle classes and ids (only first id taken into account)
1830
		$classes = array();
1831
		$id = false;
1832
		foreach ($elements as $element) {
1833
			if ($element{0} == '.') {
1834
				$classes[] = substr($element, 1);
1835
			} else if ($element{0} == '#') {
1836
				if ($id === false) $id = substr($element, 1);
1837
			}
1838
		}
1839
1840
		# compose attributes as string
1841
		$attr_str = "";
1842
		if (!empty($id)) {
1843
			$attr_str .= ' id="'.$id.'"';
1844
		}
1845
		if (!empty($classes)) {
1846
			$attr_str .= ' class="'.implode(" ", $classes).'"';
1847
		}
1848
		return $attr_str;
1849
	}
1850
1851
1852 View Code Duplication
	function stripLinkDefinitions($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1853
	#
1854
	# Strips link definitions from text, stores the URLs and titles in
1855
	# hash references.
1856
	#
1857
		$less_than_tab = $this->tab_width - 1;
1858
1859
		# Link defs are in the form: ^[id]: url "optional title"
1860
		$text = preg_replace_callback('{
1861
							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
1862
							  [ ]*
1863
							  \n?				# maybe *one* newline
1864
							  [ ]*
1865
							(?:
1866
							  <(.+?)>			# url = $2
1867
							|
1868
							  (\S+?)			# url = $3
1869
							)
1870
							  [ ]*
1871
							  \n?				# maybe one newline
1872
							  [ ]*
1873
							(?:
1874
								(?<=\s)			# lookbehind for whitespace
1875
								["(]
1876
								(.*?)			# title = $4
1877
								[")]
1878
								[ ]*
1879
							)?	# title is optional
1880
					(?:[ ]* '.$this->id_class_attr_catch_re.' )?  # $5 = extra id & class attr
1881
							(?:\n+|\Z)
1882
			}xm',
1883
			array(&$this, '_stripLinkDefinitions_callback'),
1884
			$text);
1885
		return $text;
1886
	}
1887
	function _stripLinkDefinitions_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1888
		$link_id = strtolower($matches[1]);
1889
		$url = $matches[2] == '' ? $matches[3] : $matches[2];
1890
		$this->urls[$link_id] = $url;
1891
		$this->titles[$link_id] =& $matches[4];
1892
		$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
0 ignored issues
show
Bug introduced by
The property ref_attr does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
1893
		return ''; # String that will replace the block
1894
	}
1895
1896
1897
	### HTML Block Parser ###
1898
	
1899
	# Tags that are always treated as block tags:
1900
	var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption';
1901
						   
1902
	# Tags treated as block tags only if the opening tag is alone on its line:
1903
	var $context_block_tags_re = 'script|noscript|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
1904
	
1905
	# Tags where markdown="1" default to span mode:
1906
	var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
1907
	
1908
	# Tags which must not have their contents modified, no matter where 
1909
	# they appear:
1910
	var $clean_tags_re = 'script|math|svg';
1911
	
1912
	# Tags that do not need to be closed.
1913
	var $auto_close_tags_re = 'hr|img|param|source|track';
1914
	
1915
1916
	function hashHTMLBlocks($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1917
	#
1918
	# Hashify HTML Blocks and "clean tags".
1919
	#
1920
	# We only want to do this for block-level HTML tags, such as headers,
1921
	# lists, and tables. That's because we still want to wrap <p>s around
1922
	# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
1923
	# phrase emphasis, and spans. The list of tags we're looking for is
1924
	# hard-coded.
1925
	#
1926
	# This works by calling _HashHTMLBlocks_InMarkdown, which then calls
1927
	# _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" 
1928
	# attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
1929
	#  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
1930
	# These two functions are calling each other. It's recursive!
1931
	#
1932
		if ($this->no_markup)  return $text;
1933
1934
		#
1935
		# Call the HTML-in-Markdown hasher.
1936
		#
1937
		list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
1938
		
1939
		return $text;
1940
	}
1941
	function _hashHTMLBlocks_inMarkdown($text, $indent = 0, 
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1942
										$enclosing_tag_re = '', $span = false)
1943
	{
1944
	#
1945
	# Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
1946
	#
1947
	# *   $indent is the number of space to be ignored when checking for code 
1948
	#     blocks. This is important because if we don't take the indent into 
1949
	#     account, something like this (which looks right) won't work as expected:
1950
	#
1951
	#     <div>
1952
	#         <div markdown="1">
1953
	#         Hello World.  <-- Is this a Markdown code block or text?
1954
	#         </div>  <-- Is this a Markdown code block or a real tag?
1955
	#     <div>
1956
	#
1957
	#     If you don't like this, just don't indent the tag on which
1958
	#     you apply the markdown="1" attribute.
1959
	#
1960
	# *   If $enclosing_tag_re is not empty, stops at the first unmatched closing 
1961
	#     tag with that name. Nested tags supported.
1962
	#
1963
	# *   If $span is true, text inside must treated as span. So any double 
1964
	#     newline will be replaced by a single newline so that it does not create 
1965
	#     paragraphs.
1966
	#
1967
	# Returns an array of that form: ( processed text , remaining text )
1968
	#
1969
		if ($text === '') return array('', '');
1970
1971
		# Regex to check for the presense of newlines around a block tag.
1972
		$newline_before_re = '/(?:^\n?|\n\n)*$/';
1973
		$newline_after_re = 
1974
			'{
1975
				^						# Start of text following the tag.
1976
				(?>[ ]*<!--.*?-->)?		# Optional comment.
1977
				[ ]*\n					# Must be followed by newline.
1978
			}xs';
1979
		
1980
		# Regex to match any tag.
1981
		$block_tag_re =
1982
			'{
1983
				(					# $2: Capture whole tag.
1984
					</?					# Any opening or closing tag.
1985
						(?>				# Tag name.
1986
							'.$this->block_tags_re.'			|
1987
							'.$this->context_block_tags_re.'	|
1988
							'.$this->clean_tags_re.'        	|
1989
							(?!\s)'.$enclosing_tag_re.'
1990
						)
1991
						(?:
1992
							(?=[\s"\'/a-zA-Z0-9])	# Allowed characters after tag name.
1993
							(?>
1994
								".*?"		|	# Double quotes (can contain `>`)
1995
								\'.*?\'   	|	# Single quotes (can contain `>`)
1996
								.+?				# Anything but quotes and `>`.
1997
							)*?
1998
						)?
1999
					>					# End of tag.
2000
				|
2001
					<!--    .*?     -->	# HTML Comment
2002
				|
2003
					<\?.*?\?> | <%.*?%>	# Processing instruction
2004
				|
2005
					<!\[CDATA\[.*?\]\]>	# CData Block
2006
				'. ( !$span ? ' # If not in span.
2007
				|
2008
					# Indented code block
2009
					(?: ^[ ]*\n | ^ | \n[ ]*\n )
2010
					[ ]{'.($indent+4).'}[^\n]* \n
2011
					(?>
2012
						(?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
2013
					)*
2014
				|
2015
					# Fenced code block marker
2016
					(?<= ^ | \n )
2017
					[ ]{0,'.($indent+3).'}(?:~{3,}|`{3,})
2018
									[ ]*
2019
					(?:
2020
					\.?[-_:a-zA-Z0-9]+ # standalone class name
2021
					|
2022
						'.$this->id_class_attr_nocatch_re.' # extra attributes
2023
					)?
2024
					[ ]*
2025
					(?= \n )
2026
				' : '' ). ' # End (if not is span).
2027
				|
2028
					# Code span marker
2029
					# Note, this regex needs to go after backtick fenced
2030
					# code blocks but it should also be kept outside of the
2031
					# "if not in span" condition adding backticks to the parser
2032
					`+
2033
				)
2034
			}xs';
2035
2036
		
2037
		$depth = 0;		# Current depth inside the tag tree.
2038
		$parsed = "";	# Parsed text that will be returned.
2039
2040
		#
2041
		# Loop through every tag until we find the closing tag of the parent
2042
		# or loop until reaching the end of text if no parent tag specified.
2043
		#
2044
		do {
2045
			#
2046
			# Split the text using the first $tag_match pattern found.
2047
			# Text before  pattern will be first in the array, text after
2048
			# pattern will be at the end, and between will be any catches made 
2049
			# by the pattern.
2050
			#
2051
			$parts = preg_split($block_tag_re, $text, 2, 
2052
								PREG_SPLIT_DELIM_CAPTURE);
2053
			
2054
			# If in Markdown span mode, add a empty-string span-level hash 
2055
			# after each newline to prevent triggering any block element.
2056
			if ($span) {
2057
				$void = $this->hashPart("", ':');
2058
				$newline = "$void\n";
2059
				$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
2060
			}
2061
			
2062
			$parsed .= $parts[0]; # Text before current tag.
2063
			
2064
			# If end of $text has been reached. Stop loop.
2065
			if (count($parts) < 3) {
2066
				$text = "";
2067
				break;
2068
			}
2069
			
2070
			$tag  = $parts[1]; # Tag to handle.
2071
			$text = $parts[2]; # Remaining text after current tag.
2072
			$tag_re = preg_quote($tag); # For use in a regular expression.
0 ignored issues
show
Unused Code introduced by
$tag_re is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2073
			
2074
			#
2075
			# Check for: Fenced code block marker.
2076
			# Note: need to recheck the whole tag to disambiguate backtick
2077
			# fences from code spans
2078
			#
2079
			if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) {
2080
				# Fenced code block marker: find matching end marker.
2081
				$fence_indent = strlen($capture[1]); # use captured indent in re
2082
				$fence_re = $capture[2]; # use captured fence in re
2083 View Code Duplication
				if (preg_match('{^(?>.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text,
2084
					$matches)) 
2085
				{
2086
					# End marker found: pass text unchanged until marker.
2087
					$parsed .= $tag . $matches[0];
2088
					$text = substr($text, strlen($matches[0]));
2089
				}
2090
				else {
2091
					# No end marker: just skip it.
2092
					$parsed .= $tag;
2093
				}
2094
			}
2095
			#
2096
			# Check for: Indented code block.
2097
			#
2098
			else if ($tag{0} == "\n" || $tag{0} == " ") {
2099
				# Indented code block: pass it unchanged, will be handled 
2100
				# later.
2101
				$parsed .= $tag;
2102
			}
2103
			#
2104
			# Check for: Code span marker
2105
			# Note: need to check this after backtick fenced code blocks
2106
			#
2107
			else if ($tag{0} == "`") {
2108
				# Find corresponding end marker.
2109
				$tag_re = preg_quote($tag);
2110 View Code Duplication
				if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
2111
					$text, $matches))
2112
				{
2113
					# End marker found: pass text unchanged until marker.
2114
					$parsed .= $tag . $matches[0];
2115
					$text = substr($text, strlen($matches[0]));
2116
				}
2117
				else {
2118
					# Unmatched marker: just skip it.
2119
					$parsed .= $tag;
2120
				}
2121
			}
2122
			#
2123
			# Check for: Opening Block level tag or
2124
			#            Opening Context Block tag (like ins and del) 
2125
			#               used as a block tag (tag is alone on it's line).
2126
			#
2127
			else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
2128
				(	preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
2129
					preg_match($newline_before_re, $parsed) &&
2130
					preg_match($newline_after_re, $text)	)
2131
				)
2132
			{
2133
				# Need to parse tag and following text using the HTML parser.
2134
				list($block_text, $text) = 
2135
					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
2136
				
2137
				# Make sure it stays outside of any paragraph by adding newlines.
2138
				$parsed .= "\n\n$block_text\n\n";
2139
			}
2140
			#
2141
			# Check for: Clean tag (like script, math)
2142
			#            HTML Comments, processing instructions.
2143
			#
2144
			else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
2145
				$tag{1} == '!' || $tag{1} == '?')
2146
			{
2147
				# Need to parse tag and following text using the HTML parser.
2148
				# (don't check for markdown attribute)
2149
				list($block_text, $text) = 
2150
					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
2151
				
2152
				$parsed .= $block_text;
2153
			}
2154
			#
2155
			# Check for: Tag with same name as enclosing tag.
2156
			#
2157
			else if ($enclosing_tag_re !== '' &&
2158
				# Same name as enclosing tag.
2159
				preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
2160
			{
2161
				#
2162
				# Increase/decrease nested tag count.
2163
				#
2164 View Code Duplication
				if ($tag{1} == '/')						$depth--;
2165
				else if ($tag{strlen($tag)-2} != '/')	$depth++;
2166
2167
				if ($depth < 0) {
2168
					#
2169
					# Going out of parent element. Clean up and break so we
2170
					# return to the calling function.
2171
					#
2172
					$text = $tag . $text;
2173
					break;
2174
				}
2175
				
2176
				$parsed .= $tag;
2177
			}
2178
			else {
2179
				$parsed .= $tag;
2180
			}
2181
		} while ($depth >= 0);
2182
		
2183
		return array($parsed, $text);
2184
	}
2185
	function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2186
	#
2187
	# Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
2188
	#
2189
	# *   Calls $hash_method to convert any blocks.
2190
	# *   Stops when the first opening tag closes.
2191
	# *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
2192
	#     (it is not inside clean tags)
2193
	#
2194
	# Returns an array of that form: ( processed text , remaining text )
2195
	#
2196
		if ($text === '') return array('', '');
2197
		
2198
		# Regex to match `markdown` attribute inside of a tag.
2199
		$markdown_attr_re = '
2200
			{
2201
				\s*			# Eat whitespace before the `markdown` attribute
2202
				markdown
2203
				\s*=\s*
2204
				(?>
2205
					(["\'])		# $1: quote delimiter		
2206
					(.*?)		# $2: attribute value
2207
					\1			# matching delimiter	
2208
				|
2209
					([^\s>]*)	# $3: unquoted attribute value
2210
				)
2211
				()				# $4: make $3 always defined (avoid warnings)
2212
			}xs';
2213
		
2214
		# Regex to match any tag.
2215
		$tag_re = '{
2216
				(					# $2: Capture whole tag.
2217
					</?					# Any opening or closing tag.
2218
						[\w:$]+			# Tag name.
2219
						(?:
2220
							(?=[\s"\'/a-zA-Z0-9])	# Allowed characters after tag name.
2221
							(?>
2222
								".*?"		|	# Double quotes (can contain `>`)
2223
								\'.*?\'   	|	# Single quotes (can contain `>`)
2224
								.+?				# Anything but quotes and `>`.
2225
							)*?
2226
						)?
2227
					>					# End of tag.
2228
				|
2229
					<!--    .*?     -->	# HTML Comment
2230
				|
2231
					<\?.*?\?> | <%.*?%>	# Processing instruction
2232
				|
2233
					<!\[CDATA\[.*?\]\]>	# CData Block
2234
				)
2235
			}xs';
2236
		
2237
		$original_text = $text;		# Save original text in case of faliure.
2238
		
2239
		$depth		= 0;	# Current depth inside the tag tree.
2240
		$block_text	= "";	# Temporary text holder for current text.
2241
		$parsed		= "";	# Parsed text that will be returned.
2242
2243
		#
2244
		# Get the name of the starting tag.
2245
		# (This pattern makes $base_tag_name_re safe without quoting.)
2246
		#
2247
		if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
2248
			$base_tag_name_re = $matches[1];
2249
2250
		#
2251
		# Loop through every tag until we find the corresponding closing tag.
2252
		#
2253
		do {
2254
			#
2255
			# Split the text using the first $tag_match pattern found.
2256
			# Text before  pattern will be first in the array, text after
2257
			# pattern will be at the end, and between will be any catches made 
2258
			# by the pattern.
2259
			#
2260
			$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
2261
			
2262
			if (count($parts) < 3) {
2263
				#
2264
				# End of $text reached with unbalenced tag(s).
2265
				# In that case, we return original text unchanged and pass the
2266
				# first character as filtered to prevent an infinite loop in the 
2267
				# parent function.
2268
				#
2269
				return array($original_text{0}, substr($original_text, 1));
2270
			}
2271
			
2272
			$block_text .= $parts[0]; # Text before current tag.
2273
			$tag         = $parts[1]; # Tag to handle.
2274
			$text        = $parts[2]; # Remaining text after current tag.
2275
			
2276
			#
2277
			# Check for: Auto-close tag (like <hr/>)
2278
			#			 Comments and Processing Instructions.
2279
			#
2280
			if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
2281
				$tag{1} == '!' || $tag{1} == '?')
2282
			{
2283
				# Just add the tag to the block as if it was text.
2284
				$block_text .= $tag;
2285
			}
2286
			else {
2287
				#
2288
				# Increase/decrease nested tag count. Only do so if
2289
				# the tag's name match base tag's.
2290
				#
2291
				if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
0 ignored issues
show
Bug introduced by
The variable $base_tag_name_re does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2292 View Code Duplication
					if ($tag{1} == '/')						$depth--;
2293
					else if ($tag{strlen($tag)-2} != '/')	$depth++;
2294
				}
2295
				
2296
				#
2297
				# Check for `markdown="1"` attribute and handle it.
2298
				#
2299
				if ($md_attr && 
2300
					preg_match($markdown_attr_re, $tag, $attr_m) &&
2301
					preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
2302
				{
2303
					# Remove `markdown` attribute from opening tag.
2304
					$tag = preg_replace($markdown_attr_re, '', $tag);
2305
					
2306
					# Check if text inside this tag must be parsed in span mode.
2307
					$this->mode = $attr_m[2] . $attr_m[3];
0 ignored issues
show
Bug introduced by
The property mode does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
2308
					$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
2309
						preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
2310
					
2311
					# Calculate indent before tag.
2312
					if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
2313
						$strlen = $this->utf8_strlen;
2314
						$indent = $strlen($matches[1], 'UTF-8');
2315
					} else {
2316
						$indent = 0;
2317
					}
2318
					
2319
					# End preceding block with this tag.
2320
					$block_text .= $tag;
2321
					$parsed .= $this->$hash_method($block_text);
2322
					
2323
					# Get enclosing tag name for the ParseMarkdown function.
2324
					# (This pattern makes $tag_name_re safe without quoting.)
2325
					preg_match('/^<([\w:$]*)\b/', $tag, $matches);
2326
					$tag_name_re = $matches[1];
2327
					
2328
					# Parse the content using the HTML-in-Markdown parser.
2329
					list ($block_text, $text)
2330
						= $this->_hashHTMLBlocks_inMarkdown($text, $indent, 
2331
							$tag_name_re, $span_mode);
2332
					
2333
					# Outdent markdown text.
2334
					if ($indent > 0) {
2335
						$block_text = preg_replace("/^[ ]{1,$indent}/m", "", 
2336
													$block_text);
2337
					}
2338
					
2339
					# Append tag content to parsed text.
2340
					if (!$span_mode)	$parsed .= "\n\n$block_text\n\n";
2341
					else				$parsed .= "$block_text";
2342
					
2343
					# Start over with a new block.
2344
					$block_text = "";
2345
				}
2346
				else $block_text .= $tag;
2347
			}
2348
			
2349
		} while ($depth > 0);
2350
		
2351
		#
2352
		# Hash last block text that wasn't processed inside the loop.
2353
		#
2354
		$parsed .= $this->$hash_method($block_text);
2355
		
2356
		return array($parsed, $text);
2357
	}
2358
2359
2360
	function hashClean($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2361
	#
2362
	# Called whenever a tag must be hashed when a function inserts a "clean" tag
2363
	# in $text, it passes through this function and is automaticaly escaped, 
2364
	# blocking invalid nested overlap.
2365
	#
2366
		return $this->hashPart($text, 'C');
2367
	}
2368
2369
2370 View Code Duplication
	function doAnchors($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2371
	#
2372
	# Turn Markdown link shortcuts into XHTML <a> tags.
2373
	#
2374
		if ($this->in_anchor) return $text;
2375
		$this->in_anchor = true;
2376
		
2377
		#
2378
		# First, handle reference-style links: [link text] [id]
2379
		#
2380
		$text = preg_replace_callback('{
2381
			(					# wrap whole match in $1
2382
			  \[
2383
				('.$this->nested_brackets_re.')	# link text = $2
2384
			  \]
2385
2386
			  [ ]?				# one optional space
2387
			  (?:\n[ ]*)?		# one optional newline followed by spaces
2388
2389
			  \[
2390
				(.*?)		# id = $3
2391
			  \]
2392
			)
2393
			}xs',
2394
			array(&$this, '_doAnchors_reference_callback'), $text);
2395
2396
		#
2397
		# Next, inline-style links: [link text](url "optional title")
2398
		#
2399
		$text = preg_replace_callback('{
2400
			(				# wrap whole match in $1
2401
			  \[
2402
				('.$this->nested_brackets_re.')	# link text = $2
2403
			  \]
2404
			  \(			# literal paren
2405
				[ \n]*
2406
				(?:
2407
					<(.+?)>	# href = $3
2408
				|
2409
					('.$this->nested_url_parenthesis_re.')	# href = $4
2410
				)
2411
				[ \n]*
2412
				(			# $5
2413
				  ([\'"])	# quote char = $6
2414
				  (.*?)		# Title = $7
2415
				  \6		# matching quote
2416
				  [ \n]*	# ignore any spaces/tabs between closing quote and )
2417
				)?			# title is optional
2418
			  \)
2419
			  (?:[ ]? '.$this->id_class_attr_catch_re.' )?	 # $8 = id/class attributes
2420
			)
2421
			}xs',
2422
			array(&$this, '_doAnchors_inline_callback'), $text);
2423
2424
		#
2425
		# Last, handle reference-style shortcuts: [link text]
2426
		# These must come last in case you've also got [link text][1]
2427
		# or [link text](/foo)
2428
		#
2429
		$text = preg_replace_callback('{
2430
			(					# wrap whole match in $1
2431
			  \[
2432
				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
2433
			  \]
2434
			)
2435
			}xs',
2436
			array(&$this, '_doAnchors_reference_callback'), $text);
2437
2438
		$this->in_anchor = false;
2439
		return $text;
2440
	}
2441
	function _doAnchors_reference_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2442
		$whole_match =  $matches[1];
2443
		$link_text   =  $matches[2];
2444
		$link_id     =& $matches[3];
2445
2446
		if ($link_id == "") {
2447
			# for shortcut links like [this][] or [this].
2448
			$link_id = $link_text;
2449
		}
2450
		
2451
		# lower-case and turn embedded newlines into spaces
2452
		$link_id = strtolower($link_id);
2453
		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
2454
2455
		if (isset($this->urls[$link_id])) {
2456
			$url = $this->urls[$link_id];
2457
			$url = $this->encodeAttribute($url);
2458
			
2459
			$result = "<a href=\"$url\"";
2460 View Code Duplication
			if ( isset( $this->titles[$link_id] ) ) {
2461
				$title = $this->titles[$link_id];
2462
				$title = $this->encodeAttribute($title);
2463
				$result .=  " title=\"$title\"";
2464
			}
2465
			if (isset($this->ref_attr[$link_id]))
2466
				$result .= $this->ref_attr[$link_id];
2467
		
2468
			$link_text = $this->runSpanGamut($link_text);
2469
			$result .= ">$link_text</a>";
2470
			$result = $this->hashPart($result);
2471
		}
2472
		else {
2473
			$result = $whole_match;
2474
		}
2475
		return $result;
2476
	}
2477 View Code Duplication
	function _doAnchors_inline_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2478
		$whole_match	=  $matches[1];
0 ignored issues
show
Unused Code introduced by
$whole_match is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2479
		$link_text		=  $this->runSpanGamut($matches[2]);
2480
		$url			=  $matches[3] == '' ? $matches[4] : $matches[3];
2481
		$title			=& $matches[7];
2482
		$attr  = $this->doExtraAttributes("a", $dummy =& $matches[8]);
2483
2484
2485
		$url = $this->encodeAttribute($url);
2486
2487
		$result = "<a href=\"$url\"";
2488
		if (isset($title)) {
2489
			$title = $this->encodeAttribute($title);
2490
			$result .=  " title=\"$title\"";
2491
		}
2492
		$result .= $attr;
2493
		
2494
		$link_text = $this->runSpanGamut($link_text);
2495
		$result .= ">$link_text</a>";
2496
2497
		return $this->hashPart($result);
2498
	}
2499
2500
2501 View Code Duplication
	function doImages($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2502
	#
2503
	# Turn Markdown image shortcuts into <img> tags.
2504
	#
2505
		#
2506
		# First, handle reference-style labeled images: ![alt text][id]
2507
		#
2508
		$text = preg_replace_callback('{
2509
			(				# wrap whole match in $1
2510
			  !\[
2511
				('.$this->nested_brackets_re.')		# alt text = $2
2512
			  \]
2513
2514
			  [ ]?				# one optional space
2515
			  (?:\n[ ]*)?		# one optional newline followed by spaces
2516
2517
			  \[
2518
				(.*?)		# id = $3
2519
			  \]
2520
2521
			)
2522
			}xs', 
2523
			array(&$this, '_doImages_reference_callback'), $text);
2524
2525
		#
2526
		# Next, handle inline images:  ![alt text](url "optional title")
2527
		# Don't forget: encode * and _
2528
		#
2529
		$text = preg_replace_callback('{
2530
			(				# wrap whole match in $1
2531
			  !\[
2532
				('.$this->nested_brackets_re.')		# alt text = $2
2533
			  \]
2534
			  \s?			# One optional whitespace character
2535
			  \(			# literal paren
2536
				[ \n]*
2537
				(?:
2538
					<(\S*)>	# src url = $3
2539
				|
2540
					('.$this->nested_url_parenthesis_re.')	# src url = $4
2541
				)
2542
				[ \n]*
2543
				(			# $5
2544
				  ([\'"])	# quote char = $6
2545
				  (.*?)		# title = $7
2546
				  \6		# matching quote
2547
				  [ \n]*
2548
				)?			# title is optional
2549
			  \)
2550
			  (?:[ ]? '.$this->id_class_attr_catch_re.' )?	 # $8 = id/class attributes
2551
			)
2552
			}xs',
2553
			array(&$this, '_doImages_inline_callback'), $text);
2554
2555
		return $text;
2556
	}
2557
	function _doImages_reference_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2558
		$whole_match = $matches[1];
2559
		$alt_text    = $matches[2];
2560
		$link_id     = strtolower($matches[3]);
2561
2562
		if ($link_id == "") {
2563
			$link_id = strtolower($alt_text); # for shortcut links like ![this][].
2564
		}
2565
2566
		$alt_text = $this->encodeAttribute($alt_text);
2567
		if (isset($this->urls[$link_id])) {
2568
			$url = $this->encodeAttribute($this->urls[$link_id]);
2569
			$result = "<img src=\"$url\" alt=\"$alt_text\"";
2570 View Code Duplication
			if (isset($this->titles[$link_id])) {
2571
				$title = $this->titles[$link_id];
2572
				$title = $this->encodeAttribute($title);
2573
				$result .=  " title=\"$title\"";
2574
			}
2575
			if (isset($this->ref_attr[$link_id]))
2576
				$result .= $this->ref_attr[$link_id];
2577
			$result .= $this->empty_element_suffix;
2578
			$result = $this->hashPart($result);
2579
		}
2580
		else {
2581
			# If there's no such link ID, leave intact:
2582
			$result = $whole_match;
2583
		}
2584
2585
		return $result;
2586
	}
2587 View Code Duplication
	function _doImages_inline_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2588
		$whole_match	= $matches[1];
0 ignored issues
show
Unused Code introduced by
$whole_match is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2589
		$alt_text		= $matches[2];
2590
		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
2591
		$title			=& $matches[7];
2592
		$attr  = $this->doExtraAttributes("img", $dummy =& $matches[8]);
2593
2594
		$alt_text = $this->encodeAttribute($alt_text);
2595
		$url = $this->encodeAttribute($url);
2596
		$result = "<img src=\"$url\" alt=\"$alt_text\"";
2597
		if (isset($title)) {
2598
			$title = $this->encodeAttribute($title);
2599
			$result .=  " title=\"$title\""; # $title already quoted
2600
		}
2601
		$result .= $attr;
2602
		$result .= $this->empty_element_suffix;
2603
2604
		return $this->hashPart($result);
2605
	}
2606
2607
2608
	function doHeaders($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2609
	#
2610
	# Redefined to add id and class attribute support.
2611
	#
2612
		# Setext-style headers:
2613
		#	  Header 1  {#header1}
2614
		#	  ========
2615
		#  
2616
		#	  Header 2  {#header2 .class1 .class2}
2617
		#	  --------
2618
		#
2619
		$text = preg_replace_callback(
2620
			'{
2621
				(^.+?)								# $1: Header text
2622
				(?:[ ]+ '.$this->id_class_attr_catch_re.' )?	 # $3 = id/class attributes
2623
				[ ]*\n(=+|-+)[ ]*\n+				# $3: Header footer
2624
			}mx',
2625
			array(&$this, '_doHeaders_callback_setext'), $text);
2626
2627
		# atx-style headers:
2628
		#	# Header 1        {#header1}
2629
		#	## Header 2       {#header2}
2630
		#	## Header 2 with closing hashes ##  {#header3.class1.class2}
2631
		#	...
2632
		#	###### Header 6   {.class2}
2633
		#
2634
		$text = preg_replace_callback('{
2635
				^(\#{1,6})	# $1 = string of #\'s
2636
				[ ]*
2637
				(.+?)		# $2 = Header text
2638
				[ ]*
2639
				\#*			# optional closing #\'s (not counted)
2640
				(?:[ ]+ '.$this->id_class_attr_catch_re.' )?	 # $3 = id/class attributes
2641
				[ ]*
2642
				\n+
2643
			}xm',
2644
			array(&$this, '_doHeaders_callback_atx'), $text);
2645
2646
		return $text;
2647
	}
2648
	function _doHeaders_callback_setext($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2649 View Code Duplication
		if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
2650
			return $matches[0];
2651
		$level = $matches[3]{0} == '=' ? 1 : 2;
2652
		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[2]);
2653
		$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
2654
		return "\n" . $this->hashBlock($block) . "\n\n";
2655
	}
2656
	function _doHeaders_callback_atx($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2657
		$level = strlen($matches[1]);
2658
		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[3]);
2659
		$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
2660
		return "\n" . $this->hashBlock($block) . "\n\n";
2661
	}
2662
2663
2664
	function doTables($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2665
	#
2666
	# Form HTML tables.
2667
	#
2668
		$less_than_tab = $this->tab_width - 1;
2669
		#
2670
		# Find tables with leading pipe.
2671
		#
2672
		#	| Header 1 | Header 2
2673
		#	| -------- | --------
2674
		#	| Cell 1   | Cell 2
2675
		#	| Cell 3   | Cell 4
2676
		#
2677
		$text = preg_replace_callback('
2678
			{
2679
				^							# Start of a line
2680
				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
2681
				[|]							# Optional leading pipe (present)
2682
				(.+) \n						# $1: Header row (at least one pipe)
2683
				
2684
				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
2685
				[|] ([ ]*[-:]+[-| :]*) \n	# $2: Header underline
2686
				
2687
				(							# $3: Cells
2688
					(?>
2689
						[ ]*				# Allowed whitespace.
2690
						[|] .* \n			# Row content.
2691
					)*
2692
				)
2693
				(?=\n|\Z)					# Stop at final double newline.
2694
			}xm',
2695
			array(&$this, '_doTable_leadingPipe_callback'), $text);
2696
		
2697
		#
2698
		# Find tables without leading pipe.
2699
		#
2700
		#	Header 1 | Header 2
2701
		#	-------- | --------
2702
		#	Cell 1   | Cell 2
2703
		#	Cell 3   | Cell 4
2704
		#
2705
		$text = preg_replace_callback('
2706
			{
2707
				^							# Start of a line
2708
				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
2709
				(\S.*[|].*) \n				# $1: Header row (at least one pipe)
2710
				
2711
				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
2712
				([-:]+[ ]*[|][-| :]*) \n	# $2: Header underline
2713
				
2714
				(							# $3: Cells
2715
					(?>
2716
						.* [|] .* \n		# Row content
2717
					)*
2718
				)
2719
				(?=\n|\Z)					# Stop at final double newline.
2720
			}xm',
2721
			array(&$this, '_DoTable_callback'), $text);
2722
2723
		return $text;
2724
	}
2725
	function _doTable_leadingPipe_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2726
		$head		= $matches[1];
2727
		$underline	= $matches[2];
2728
		$content	= $matches[3];
2729
		
2730
		# Remove leading pipe for each row.
2731
		$content	= preg_replace('/^ *[|]/m', '', $content);
2732
		
2733
		return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
2734
	}
2735
	function _doTable_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2736
		$head		= $matches[1];
2737
		$underline	= $matches[2];
2738
		$content	= $matches[3];
2739
2740
		# Remove any tailing pipes for each line.
2741
		$head		= preg_replace('/[|] *$/m', '', $head);
2742
		$underline	= preg_replace('/[|] *$/m', '', $underline);
2743
		$content	= preg_replace('/[|] *$/m', '', $content);
2744
		
2745
		# Reading alignement from header underline.
2746
		$separators	= preg_split('/ *[|] */', $underline);
2747
		foreach ($separators as $n => $s) {
2748
			if (preg_match('/^ *-+: *$/', $s))		$attr[$n] = ' align="right"';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$attr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $attr = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
2749
			else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
0 ignored issues
show
Bug introduced by
The variable $attr does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2750
			else if (preg_match('/^ *:-+ *$/', $s))	$attr[$n] = ' align="left"';
2751
			else									$attr[$n] = '';
2752
		}
2753
		
2754
		# Parsing span elements, including code spans, character escapes, 
2755
		# and inline HTML tags, so that pipes inside those gets ignored.
2756
		$head		= $this->parseSpan($head);
2757
		$headers	= preg_split('/ *[|] */', $head);
2758
		$col_count	= count($headers);
2759
		$attr       = array_pad($attr, $col_count, '');
2760
		
2761
		# Write column headers.
2762
		$text = "<table>\n";
2763
		$text .= "<thead>\n";
2764
		$text .= "<tr>\n";
2765
		foreach ($headers as $n => $header)
2766
			$text .= "  <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
2767
		$text .= "</tr>\n";
2768
		$text .= "</thead>\n";
2769
		
2770
		# Split content by row.
2771
		$rows = explode("\n", trim($content, "\n"));
2772
		
2773
		$text .= "<tbody>\n";
2774
		foreach ($rows as $row) {
2775
			# Parsing span elements, including code spans, character escapes, 
2776
			# and inline HTML tags, so that pipes inside those gets ignored.
2777
			$row = $this->parseSpan($row);
2778
			
2779
			# Split row by cell.
2780
			$row_cells = preg_split('/ *[|] */', $row, $col_count);
2781
			$row_cells = array_pad($row_cells, $col_count, '');
2782
			
2783
			$text .= "<tr>\n";
2784
			foreach ($row_cells as $n => $cell)
2785
				$text .= "  <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
2786
			$text .= "</tr>\n";
2787
		}
2788
		$text .= "</tbody>\n";
2789
		$text .= "</table>";
2790
		
2791
		return $this->hashBlock($text) . "\n";
2792
	}
2793
2794
	
2795
	function doDefLists($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2796
	#
2797
	# Form HTML definition lists.
2798
	#
2799
		$less_than_tab = $this->tab_width - 1;
2800
2801
		# Re-usable pattern to match any entire dl list:
2802
		$whole_list_re = '(?>
2803
			(								# $1 = whole list
2804
			  (								# $2
2805
				[ ]{0,'.$less_than_tab.'}
2806
				((?>.*\S.*\n)+)				# $3 = defined term
2807
				\n?
2808
				[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
2809
			  )
2810
			  (?s:.+?)
2811
			  (								# $4
2812
				  \z
2813
				|
2814
				  \n{2,}
2815
				  (?=\S)
2816
				  (?!						# Negative lookahead for another term
2817
					[ ]{0,'.$less_than_tab.'}
2818
					(?: \S.*\n )+?			# defined term
2819
					\n?
2820
					[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
2821
				  )
2822
				  (?!						# Negative lookahead for another definition
2823
					[ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
2824
				  )
2825
			  )
2826
			)
2827
		)'; // mx
2828
2829
		$text = preg_replace_callback('{
2830
				(?>\A\n?|(?<=\n\n))
2831
				'.$whole_list_re.'
2832
			}mx',
2833
			array(&$this, '_doDefLists_callback'), $text);
2834
2835
		return $text;
2836
	}
2837
	function _doDefLists_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2838
		# Re-usable patterns to match list item bullets and number markers:
2839
		$list = $matches[1];
2840
		
2841
		# Turn double returns into triple returns, so that we can make a
2842
		# paragraph for the last item in a list, if necessary:
2843
		$result = trim($this->processDefListItems($list));
2844
		$result = "<dl>\n" . $result . "\n</dl>";
2845
		return $this->hashBlock($result) . "\n\n";
2846
	}
2847
2848
2849
	function processDefListItems($list_str) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2850
	#
2851
	#	Process the contents of a single definition list, splitting it
2852
	#	into individual term and definition list items.
2853
	#
2854
		$less_than_tab = $this->tab_width - 1;
2855
		
2856
		# trim trailing blank lines:
2857
		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
2858
2859
		# Process definition terms.
2860
		$list_str = preg_replace_callback('{
2861
			(?>\A\n?|\n\n+)					# leading line
2862
			(								# definition terms = $1
2863
				[ ]{0,'.$less_than_tab.'}	# leading whitespace
2864
				(?!\:[ ]|[ ])				# negative lookahead for a definition
2865
											#   mark (colon) or more whitespace.
2866
				(?> \S.* \n)+?				# actual term (not whitespace).	
2867
			)			
2868
			(?=\n?[ ]{0,3}:[ ])				# lookahead for following line feed 
2869
											#   with a definition mark.
2870
			}xm',
2871
			array(&$this, '_processDefListItems_callback_dt'), $list_str);
2872
2873
		# Process actual definitions.
2874
		$list_str = preg_replace_callback('{
2875
			\n(\n+)?						# leading line = $1
2876
			(								# marker space = $2
2877
				[ ]{0,'.$less_than_tab.'}	# whitespace before colon
2878
				\:[ ]+						# definition mark (colon)
2879
			)
2880
			((?s:.+?))						# definition text = $3
2881
			(?= \n+ 						# stop at next definition mark,
2882
				(?:							# next term or end of text
2883
					[ ]{0,'.$less_than_tab.'} \:[ ]	|
2884
					<dt> | \z
2885
				)						
2886
			)					
2887
			}xm',
2888
			array(&$this, '_processDefListItems_callback_dd'), $list_str);
2889
2890
		return $list_str;
2891
	}
2892
	function _processDefListItems_callback_dt($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2893
		$terms = explode("\n", trim($matches[1]));
2894
		$text = '';
2895
		foreach ($terms as $term) {
2896
			$term = $this->runSpanGamut(trim($term));
2897
			$text .= "\n<dt>" . $term . "</dt>";
2898
		}
2899
		return $text . "\n";
2900
	}
2901
	function _processDefListItems_callback_dd($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2902
		$leading_line	= $matches[1];
2903
		$marker_space	= $matches[2];
2904
		$def			= $matches[3];
2905
2906 View Code Duplication
		if ($leading_line || preg_match('/\n{2,}/', $def)) {
2907
			# Replace marker with the appropriate whitespace indentation
2908
			$def = str_repeat(' ', strlen($marker_space)) . $def;
2909
			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
2910
			$def = "\n". $def ."\n";
2911
		}
2912
		else {
2913
			$def = rtrim($def);
2914
			$def = $this->runSpanGamut($this->outdent($def));
2915
		}
2916
2917
		return "\n<dd>" . $def . "</dd>\n";
2918
	}
2919
2920
2921 View Code Duplication
	function doFencedCodeBlocks($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2922
	#
2923
	# Adding the fenced code block syntax to regular Markdown:
2924
	#
2925
	# ~~~
2926
	# Code block
2927
	# ~~~
2928
	#
2929
		$less_than_tab = $this->tab_width;
0 ignored issues
show
Unused Code introduced by
$less_than_tab is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
2930
		
2931
		$text = preg_replace_callback('{
2932
				(?:\n|\A)
2933
				# 1: Opening marker
2934
				(
2935
					(?:~{3,}|`{3,}) # 3 or more tildes/backticks.
2936
				)
2937
				[ ]*
2938
				(?:
2939
					\.?([-_:a-zA-Z0-9]+) # 2: standalone class name
2940
				|
2941
					'.$this->id_class_attr_catch_re.' # 3: Extra attributes
2942
				)?
2943
				[ ]* \n # Whitespace and newline following marker.
2944
				
2945
				# 4: Content
2946
				(
2947
					(?>
2948
						(?!\1 [ ]* \n)	# Not a closing marker.
2949
						.*\n+
2950
					)+
2951
				)
2952
				
2953
				# Closing marker.
2954
				\1 [ ]* (?= \n )
2955
			}xm',
2956
			array(&$this, '_doFencedCodeBlocks_callback'), $text);
2957
2958
		return $text;
2959
	}
2960
	function _doFencedCodeBlocks_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2961
		$classname =& $matches[2];
2962
		$attrs     =& $matches[3];
2963
		$codeblock = $matches[4];
2964
		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
2965
		$codeblock = preg_replace_callback('/^\n+/',
2966
			array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
2967
2968
		if ($classname != "") {
2969
			if ($classname{0} == '.')
2970
				$classname = substr($classname, 1);
2971
			$attr_str = ' class="'.$this->code_class_prefix.$classname.'"';
2972
		} else {
2973
			$attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs);
2974
		}
2975
		$pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
2976
		$code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
2977
		$codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
2978
		
2979
		return "\n\n".$this->hashBlock($codeblock)."\n\n";
2980
	}
2981
	function _doFencedCodeBlocks_newlines($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2982
		return str_repeat("<br$this->empty_element_suffix", 
2983
			strlen($matches[0]));
2984
	}
2985
2986
2987
	#
2988
	# Redefining emphasis markers so that emphasis by underscore does not
2989
	# work in the middle of a word.
2990
	#
2991
	var $em_relist = array(
2992
		''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S|$)(?![\.,:;]\s)',
2993
		'*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
2994
		'_' => '(?<=\S|^)(?<!_)_(?![a-zA-Z0-9_])',
2995
		);
2996
	var $strong_relist = array(
2997
		''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S|$)(?![\.,:;]\s)',
2998
		'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
2999
		'__' => '(?<=\S|^)(?<!_)__(?![a-zA-Z0-9_])',
3000
		);
3001
	var $em_strong_relist = array(
3002
		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S|$)(?![\.,:;]\s)',
3003
		'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
3004
		'___' => '(?<=\S|^)(?<!_)___(?![a-zA-Z0-9_])',
3005
		);
3006
3007
3008
	function formParagraphs($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3009
	#
3010
	#	Params:
3011
	#		$text - string to process with html <p> tags
3012
	#
3013
		# Strip leading and trailing lines:
3014
		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
3015
		
3016
		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
3017
3018
		#
3019
		# Wrap <p> tags and unhashify HTML blocks
3020
		#
3021
		foreach ($grafs as $key => $value) {
3022
			$value = trim($this->runSpanGamut($value));
3023
			
3024
			# Check if this should be enclosed in a paragraph.
3025
			# Clean tag hashes & block tag hashes are left alone.
3026
			$is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
3027
			
3028
			if ($is_p) {
3029
				$value = "<p>$value</p>";
3030
			}
3031
			$grafs[$key] = $value;
3032
		}
3033
		
3034
		# Join grafs in one text, then unhash HTML tags. 
3035
		$text = implode("\n\n", $grafs);
3036
		
3037
		# Finish by removing any tag hashes still present in $text.
3038
		$text = $this->unhash($text);
3039
		
3040
		return $text;
3041
	}
3042
	
3043
	
3044
	### Footnotes
3045
	
3046 View Code Duplication
	function stripFootnotes($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3047
	#
3048
	# Strips link definitions from text, stores the URLs and titles in
3049
	# hash references.
3050
	#
3051
		$less_than_tab = $this->tab_width - 1;
3052
3053
		# Link defs are in the form: [^id]: url "optional title"
3054
		$text = preg_replace_callback('{
3055
			^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?:	# note_id = $1
3056
			  [ ]*
3057
			  \n?					# maybe *one* newline
3058
			(						# text = $2 (no blank lines allowed)
3059
				(?:					
3060
					.+				# actual text
3061
				|
3062
					\n				# newlines but 
3063
					(?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
3064
					(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed 
3065
									# by non-indented content
3066
				)*
3067
			)		
3068
			}xm',
3069
			array(&$this, '_stripFootnotes_callback'),
3070
			$text);
3071
		return $text;
3072
	}
3073
	function _stripFootnotes_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3074
		$note_id = $this->fn_id_prefix . $matches[1];
3075
		$this->footnotes[$note_id] = $this->outdent($matches[2]);
3076
		return ''; # String that will replace the block
3077
	}
3078
3079
3080
	function doFootnotes($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3081
	#
3082
	# Replace footnote references in $text [^id] with a special text-token 
3083
	# which will be replaced by the actual footnote marker in appendFootnotes.
3084
	#
3085
		if (!$this->in_anchor) {
3086
			$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
3087
		}
3088
		return $text;
3089
	}
3090
3091
	
3092
	function appendFootnotes($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3093
	#
3094
	# Append footnote list to text.
3095
	#
3096
		$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
3097
			array(&$this, '_appendFootnotes_callback'), $text);
3098
	
3099
		if (!empty($this->footnotes_ordered)) {
3100
			$text .= "\n\n";
3101
			$text .= "<div class=\"footnotes\">\n";
3102
			$text .= "<hr". $this->empty_element_suffix ."\n";
3103
			$text .= "<ol>\n\n";
3104
			
3105
			$attr = " rev=\"footnote\"";
3106
			if ($this->fn_backlink_class != "") {
3107
				$class = $this->fn_backlink_class;
3108
				$class = $this->encodeAttribute($class);
3109
				$attr .= " class=\"$class\"";
3110
			}
3111
			if ($this->fn_backlink_title != "") {
3112
				$title = $this->fn_backlink_title;
3113
				$title = $this->encodeAttribute($title);
3114
				$attr .= " title=\"$title\"";
3115
			}
3116
			$num = 0;
3117
			
3118
			while (!empty($this->footnotes_ordered)) {
3119
				$footnote = reset($this->footnotes_ordered);
3120
				$note_id = key($this->footnotes_ordered);
3121
				unset($this->footnotes_ordered[$note_id]);
3122
				$ref_count = $this->footnotes_ref_count[$note_id];
3123
				unset($this->footnotes_ref_count[$note_id]);
3124
				unset($this->footnotes[$note_id]);
3125
				
3126
				$footnote .= "\n"; # Need to append newline before parsing.
3127
				$footnote = $this->runBlockGamut("$footnote\n");				
3128
				$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
3129
					array(&$this, '_appendFootnotes_callback'), $footnote);
3130
				
3131
				$attr = str_replace("%%", ++$num, $attr);
3132
				$note_id = $this->encodeAttribute($note_id);
3133
3134
				# Prepare backlink, multiple backlinks if multiple references
3135
				$backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
3136
				for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
3137
					$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>&#8617;</a>";
3138
				}
3139
				# Add backlink to last paragraph; create new paragraph if needed.
3140
				if (preg_match('{</p>$}', $footnote)) {
3141
					$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
3142
				} else {
3143
					$footnote .= "\n\n<p>$backlink</p>";
3144
				}
3145
				
3146
				$text .= "<li id=\"fn:$note_id\">\n";
3147
				$text .= $footnote . "\n";
3148
				$text .= "</li>\n\n";
3149
			}
3150
			
3151
			$text .= "</ol>\n";
3152
			$text .= "</div>";
3153
		}
3154
		return $text;
3155
	}
3156
	function _appendFootnotes_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3157
		$node_id = $this->fn_id_prefix . $matches[1];
3158
		
3159
		# Create footnote marker only if it has a corresponding footnote *and*
3160
		# the footnote hasn't been used by another marker.
3161
		if (isset($this->footnotes[$node_id])) {
3162
			$num =& $this->footnotes_numbers[$node_id];
3163
			if (!isset($num)) {
3164
				# Transfer footnote content to the ordered list and give it its
3165
				# number
3166
				$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
3167
				$this->footnotes_ref_count[$node_id] = 1;
3168
				$num = $this->footnote_counter++;
3169
				$ref_count_mark = '';
3170
			} else {
3171
				$ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
3172
			}
3173
			
3174
			$attr = " rel=\"footnote\"";
3175
			if ($this->fn_link_class != "") {
3176
				$class = $this->fn_link_class;
3177
				$class = $this->encodeAttribute($class);
3178
				$attr .= " class=\"$class\"";
3179
			}
3180
			if ($this->fn_link_title != "") {
3181
				$title = $this->fn_link_title;
3182
				$title = $this->encodeAttribute($title);
3183
				$attr .= " title=\"$title\"";
3184
			}
3185
			
3186
			$attr = str_replace("%%", $num, $attr);
3187
			$node_id = $this->encodeAttribute($node_id);
3188
			
3189
			return
3190
				"<sup id=\"fnref$ref_count_mark:$node_id\">".
3191
				"<a href=\"#fn:$node_id\"$attr>$num</a>".
3192
				"</sup>";
3193
		}
3194
		
3195
		return "[^".$matches[1]."]";
3196
	}
3197
		
3198
	
3199
	### Abbreviations ###
3200
	
3201 View Code Duplication
	function stripAbbreviations($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
3202
	#
3203
	# Strips abbreviations from text, stores titles in hash references.
3204
	#
3205
		$less_than_tab = $this->tab_width - 1;
3206
3207
		# Link defs are in the form: [id]*: url "optional title"
3208
		$text = preg_replace_callback('{
3209
			^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?:	# abbr_id = $1
3210
			(.*)					# text = $2 (no blank lines allowed)	
3211
			}xm',
3212
			array(&$this, '_stripAbbreviations_callback'),
3213
			$text);
3214
		return $text;
3215
	}
3216
	function _stripAbbreviations_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3217
		$abbr_word = $matches[1];
3218
		$abbr_desc = $matches[2];
3219
		if ($this->abbr_word_re)
3220
			$this->abbr_word_re .= '|';
3221
		$this->abbr_word_re .= preg_quote($abbr_word);
3222
		$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
3223
		return ''; # String that will replace the block
3224
	}
3225
	
3226
	
3227
	function doAbbreviations($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3228
	#
3229
	# Find defined abbreviations in text and wrap them in <abbr> elements.
3230
	#
3231
		if ($this->abbr_word_re) {
3232
			// cannot use the /x modifier because abbr_word_re may 
3233
			// contain significant spaces:
3234
			$text = preg_replace_callback('{'.
3235
				'(?<![\w\x1A])'.
3236
				'(?:'.$this->abbr_word_re.')'.
3237
				'(?![\w\x1A])'.
3238
				'}', 
3239
				array(&$this, '_doAbbreviations_callback'), $text);
3240
		}
3241
		return $text;
3242
	}
3243
	function _doAbbreviations_callback($matches) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3244
		$abbr = $matches[0];
3245
		if (isset($this->abbr_desciptions[$abbr])) {
3246
			$desc = $this->abbr_desciptions[$abbr];
3247
			if (empty($desc)) {
3248
				return $this->hashPart("<abbr>$abbr</abbr>");
3249
			} else {
3250
				$desc = $this->encodeAttribute($desc);
3251
				return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
3252
			}
3253
		} else {
3254
			return $matches[0];
3255
		}
3256
	}
3257
3258
}
3259
3260
3261
/*
3262
3263
PHP Markdown Extra
3264
==================
3265
3266
Description
3267
-----------
3268
3269
This is a PHP port of the original Markdown formatter written in Perl 
3270
by John Gruber. This special "Extra" version of PHP Markdown features 
3271
further enhancements to the syntax for making additional constructs 
3272
such as tables and definition list.
3273
3274
Markdown is a text-to-HTML filter; it translates an easy-to-read /
3275
easy-to-write structured text format into HTML. Markdown's text format
3276
is mostly similar to that of plain text email, and supports features such
3277
as headers, *emphasis*, code blocks, blockquotes, and links.
3278
3279
Markdown's syntax is designed not as a generic markup language, but
3280
specifically to serve as a front-end to (X)HTML. You can use span-level
3281
HTML tags anywhere in a Markdown document, and you can use block level
3282
HTML tags (like <div> and <table> as well).
3283
3284
For more information about Markdown's syntax, see:
3285
3286
<http://daringfireball.net/projects/markdown/>
3287
3288
3289
Bugs
3290
----
3291
3292
To file bug reports please send email to:
3293
3294
<[email protected]>
3295
3296
Please include with your report: (1) the example input; (2) the output you
3297
expected; (3) the output Markdown actually produced.
3298
3299
3300
Version History
3301
--------------- 
3302
3303
See the readme file for detailed release notes for this version.
3304
3305
3306
Copyright and License
3307
---------------------
3308
3309
PHP Markdown & Extra
3310
Copyright (c) 2004-2013 Michel Fortin
3311
<http://michelf.ca/>  
3312
All rights reserved.
3313
3314
Based on Markdown  
3315
Copyright (c) 2003-2006 John Gruber   
3316
<http://daringfireball.net/>   
3317
All rights reserved.
3318
3319
Redistribution and use in source and binary forms, with or without
3320
modification, are permitted provided that the following conditions are
3321
met:
3322
3323
*	Redistributions of source code must retain the above copyright notice,
3324
	this list of conditions and the following disclaimer.
3325
3326
*	Redistributions in binary form must reproduce the above copyright
3327
	notice, this list of conditions and the following disclaimer in the
3328
	documentation and/or other materials provided with the distribution.
3329
3330
*	Neither the name "Markdown" nor the names of its contributors may
3331
	be used to endorse or promote products derived from this software
3332
	without specific prior written permission.
3333
3334
This software is provided by the copyright holders and contributors "as
3335
is" and any express or implied warranties, including, but not limited
3336
to, the implied warranties of merchantability and fitness for a
3337
particular purpose are disclaimed. In no event shall the copyright owner
3338
or contributors be liable for any direct, indirect, incidental, special,
3339
exemplary, or consequential damages (including, but not limited to,
3340
procurement of substitute goods or services; loss of use, data, or
3341
profits; or business interruption) however caused and on any theory of
3342
liability, whether in contract, strict liability, or tort (including
3343
negligence or otherwise) arising in any way out of the use of this
3344
software, even if advised of the possibility of such damage.
3345
3346
*/
3347
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
3348