Completed
Pull Request — master (#2278)
by ྅༻ Ǭɀħ
14:42
created

includes/functions-html.php (15 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Display <h1> header and logo
5
 *
6
 */
7
function yourls_html_logo() {
8
	yourls_do_action( 'pre_html_logo' );
9
	?>
10
	<header role="banner">
11
	<h1>
12
		<a href="<?php echo yourls_admin_url( 'index.php' ) ?>" title="YOURLS"><span>YOURLS</span>: <span>Y</span>our <span>O</span>wn <span>URL</span> <span>S</span>hortener<br/>
13
		<img src="<?php yourls_site_url(); ?>/images/yourls-logo.png" alt="YOURLS" title="YOURLS" border="0" style="border: 0px;" /></a>
14
	</h1>
15
	</header>
16
	<?php
17
	yourls_do_action( 'html_logo' );
18
}
19
20
/**
21
 * Display HTML head and <body> tag
22
 *
23
 * @param string $context Context of the page (stats, index, infos, ...)
24
 * @param string $title HTML title of the page
25
 */
26
function yourls_html_head( $context = 'index', $title = '' ) {
27
28
	yourls_do_action( 'pre_html_head', $context, $title );
29
	
30
	// All components to false, except when specified true
31
	$share = $insert = $tablesorter = $tabs = $cal = $charts = false;
32
	
33
	// Load components as needed
34
	switch ( $context ) {
35
		case 'infos':
36
			$share = $tabs = $charts = true;
37
			break;
38
			
39
		case 'bookmark':
40
			$share = $insert = $tablesorter = true;
41
			break;
42
			
43
		case 'index':
44
			$insert = $tablesorter = $cal = $share = true;
45
			break;
46
			
47
		case 'plugins':
48
		case 'tools':
49
			$tablesorter = true;
50
			break;
51
		
52
		case 'install':
53
		case 'login':
54
		case 'new':
55
		case 'upgrade':
56
			break;
57
	}
58
	
59
	// Force no cache for all admin pages
60
	if( yourls_is_admin() && !headers_sent() ) {
61
		header( 'Expires: Thu, 23 Mar 1972 07:00:00 GMT' );
62
		header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
63
		header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
64
		header( 'Pragma: no-cache' );
65
		yourls_content_type_header( yourls_apply_filter( 'html_head_content-type', 'text/html' ) );
66
		yourls_do_action( 'admin_headers', $context, $title );
67
	}
68
	
69
	// Store page context in global object
70
	global $ydb;
71
	$ydb->context = $context;
72
	
73
	// Body class
74
	$bodyclass = yourls_apply_filter( 'bodyclass', '' );
75
	$bodyclass .= ( yourls_is_mobile_device() ? 'mobile' : 'desktop' );
76
	
77
	// Page title
78
	$_title = 'YOURLS &mdash; Your Own URL Shortener | ' . yourls_link();
79
	$title = $title ? $title . " &laquo; " . $_title : $_title;
80
	$title = yourls_apply_filter( 'html_title', $title, $context );
81
	
82
	?>
83
<!DOCTYPE html>
84
<html <?php yourls_html_language_attributes(); ?>>
85
<head>
86
	<title><?php echo $title ?></title>
87
	<meta http-equiv="Content-Type" content="<?php echo yourls_apply_filter( 'html_head_meta_content-type', 'text/html; charset=utf-8' ); ?>" />
88
	<meta name="generator" content="YOURLS <?php echo YOURLS_VERSION ?>" />
89
	<meta name="description" content="YOURLS &raquo; Your Own URL Shortener' | <?php yourls_site_url(); ?>" />
90
	<meta name="referrer" content="always" />
91
	<?php yourls_do_action('html_head_meta', $context); ?>
92
	<link rel="shortcut icon" href="<?php yourls_favicon(); ?>" />
93
	<script src="<?php yourls_site_url(); ?>/js/jquery-2.2.4.min.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
94
	<script src="<?php yourls_site_url(); ?>/js/common.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
95
	<script src="<?php yourls_site_url(); ?>/js/jquery.notifybar.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
96
	<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/style.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
97 View Code Duplication
	<?php if ( $tabs ) { ?>
0 ignored issues
show
This code seems to be duplicated across 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...
98
		<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/infos.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
99
		<script src="<?php yourls_site_url(); ?>/js/infos.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
100
	<?php } ?>
101 View Code Duplication
	<?php if ( $tablesorter ) { ?>
0 ignored issues
show
This code seems to be duplicated across 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...
102
		<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/tablesorter.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
103
		<script src="<?php yourls_site_url(); ?>/js/jquery.tablesorter.min.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
104
	<?php } ?>
105
	<?php if ( $insert ) { ?>
106
		<script src="<?php yourls_site_url(); ?>/js/insert.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
107
	<?php } ?>
108
	<?php if ( $share ) { ?>
109
		<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/share.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
110
		<script src="<?php yourls_site_url(); ?>/js/share.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
111
		<script src="<?php yourls_site_url(); ?>/js/clipboard.min.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
112
	<?php } ?>
113 View Code Duplication
	<?php if ( $cal ) { ?>
0 ignored issues
show
This code seems to be duplicated across 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...
114
		<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/cal.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
115
		<?php yourls_l10n_calendar_strings(); ?>
116
		<script src="<?php yourls_site_url(); ?>/js/jquery.cal.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
117
	<?php } ?>
118
	<?php if ( $charts ) { ?>
119
			<script type="text/javascript" src="https://www.google.com/jsapi"></script>
120
			<script type="text/javascript">
121
					 google.load('visualization', '1.0', {'packages':['corechart', 'geochart']});
122
			</script>
123
	<?php } ?>
124
	<script type="text/javascript">
125
	//<![CDATA[
126
		var ajaxurl  = '<?php echo yourls_admin_url( 'admin-ajax.php' ); ?>';
127
	//]]>
128
	</script>
129
	<?php yourls_do_action( 'html_head', $context ); ?>
130
</head>
131
<body class="<?php echo $context; ?> <?php echo $bodyclass; ?>">
132
<div id="wrap">
133
	<?php
134
}
135
136
/**
137
 * Display HTML footer (including closing body & html tags)
138
 *
139
 */
140
function yourls_html_footer() {
141
	global $ydb;
142
	
143
	$num_queries = sprintf( yourls_n( '1 query', '%s queries', $ydb->num_queries ), $ydb->num_queries );
144
	?>
145
	</div><?php // wrap ?>
146
	<footer id="footer" role="contentinfo"><p>
147
		<?php
148
		$footer  = yourls_s( 'Powered by %s', '<a href="http://yourls.org/" title="YOURLS">YOURLS</a> v ' . YOURLS_VERSION );
149
		$footer .= ' &ndash; '.$num_queries;
150
		echo yourls_apply_filter( 'html_footer_text', $footer );
151
		?>
152
	</p></footer>
153
	<?php if( defined( 'YOURLS_DEBUG' ) && YOURLS_DEBUG == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
154
		echo '<div style="text-align:left"><pre>';
155
		echo join( "\n", $ydb->debug_log );
156
		echo '</div>';
157
	} ?>
158
	<?php yourls_do_action( 'html_footer', $ydb->context ); ?>
159
	</body>
160
	</html>
161
	<?php
162
}
163
164
/**
165
 * Display "Add new URL" box
166
 *
167
 * @param string $url URL to prefill the input with
168
 * @param string $keyword Keyword to prefill the input with
169
 */
170
function yourls_html_addnew( $url = '', $keyword = '' ) {
171
	?>
172
	<main role="main">
173
	<div id="new_url">
174
		<div>
175
			<form id="new_url_form" action="" method="get">
176
				<div><strong><?php yourls_e( 'Enter the URL' ); ?></strong>:<input type="text" id="add-url" name="url" value="<?php echo $url; ?>" class="text" size="80" placeholder="http://" />
177
				<?php yourls_e( 'Optional '); ?> : <strong><?php yourls_e('Custom short URL'); ?></strong>:<input type="text" id="add-keyword" name="keyword" value="<?php echo $keyword; ?>" class="text" size="8" />
178
				<?php yourls_nonce_field( 'add_url', 'nonce-add' ); ?>
179
				<input type="button" id="add-button" name="add-button" value="<?php yourls_e( 'Shorten The URL' ); ?>" class="button" onclick="add_link();" /></div>
180
			</form>
181
			<div id="feedback" style="display:none"></div>
182
		</div>
183
		<?php yourls_do_action( 'html_addnew' ); ?>
184
	</div>
185
	<?php 
186
}
187
188
/**
189
 * Display main table's footer
190
 *
191
 * The $param array is defined in /admin/index.php, check the yourls_html_tfooter() call
192
 *
193
 * @param array $params Array of all required parameters
194
 * @return string Result
195
 */
196
function yourls_html_tfooter( $params = array() ) {
197
    // Manually extract all parameters from the array. We prefer doing it this way, over using extract(),
198
    // to make things clearer and more explicit about what var is used.
199
    $search       = $params['search'];
0 ignored issues
show
$search 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...
200
    $search_text  = $params['search_text'];
201
    $search_in    = $params['search_in'];
202
    $sort_by      = $params['sort_by'];
203
    $sort_order   = $params['sort_order'];
204
    $page         = $params['page'];
205
    $perpage      = $params['perpage'];
206
    $click_filter = $params['click_filter'];
207
    $click_limit  = $params['click_limit'];
208
    $total_pages  = $params['total_pages'];
209
    $date_filter  = $params['date_filter'];
210
    $date_first   = $params['date_first'];
211
    $date_second  = $params['date_second'];
212
213
	?>
214
	<tfoot>
215
		<tr>
216
			<th colspan="6">
217
			<div id="filter_form">
218
				<form action="" method="get">
219
					<div id="filter_options">
220
						<?php
221
						
222
						// First search control: text to search
223
						$_input = '<input type="text" name="search" class="text" size="12" value="' . yourls_esc_attr( $search_text ) . '" />';
224
						$_options = array(
225
                            'all'     => yourls__( 'All fields' ),
226
							'keyword' => yourls__( 'Short URL' ),
227
							'url'     => yourls__( 'URL' ),
228
							'title'   => yourls__( 'Title' ),
229
							'ip'      => yourls__( 'IP' ),
230
						);							
231
						$_select = yourls_html_select( 'search_in', $_options, $search_in );
232
						/* //translators: "Search for <input field with text to search> in <select dropdown with URL, title...>" */
233
						yourls_se( 'Search for %1$s in %2$s', $_input , $_select );
234
						echo "&ndash;\n";
235
						
236
						// Second search control: order by
237
						$_options = array(
238
							'keyword'      => yourls__( 'Short URL' ),
239
							'url'          => yourls__( 'URL' ),
240
							'timestamp'    => yourls__( 'Date' ),
241
							'ip'           => yourls__( 'IP' ),
242
							'clicks'       => yourls__( 'Clicks' ),
243
						);
244
						$_select = yourls_html_select( 'sort_by', $_options, $sort_by );
245
						$sort_order = isset( $sort_order ) ? $sort_order : 'desc' ;
246
						$_options = array(
247
							'asc'  => yourls__( 'Ascending' ),
248
							'desc' => yourls__( 'Descending' ),
249
						);
250
						$_select2 = yourls_html_select( 'sort_order', $_options, $sort_order );
251
						/* //translators: "Order by <criteria dropdown (date, clicks...)> in <order dropdown (Descending or Ascending)>" */
252
						yourls_se( 'Order by %1$s %2$s', $_select , $_select2 );
253
						echo "&ndash;\n";
254
						
255
						// Third search control: Show XX rows
256
						/* //translators: "Show <text field> rows" */
257
						yourls_se( 'Show %s rows',  '<input type="text" name="perpage" class="text" size="2" value="' . $perpage . '" />' );
258
						echo "<br/>\n";
259
260
						// Fourth search control: Show links with more than XX clicks
261
						$_options = array(
262
							'more' => yourls__( 'more' ),
263
							'less' => yourls__( 'less' ),
264
						);
265
						$_select = yourls_html_select( 'click_filter', $_options, $click_filter );
266
						$_input  = '<input type="text" name="click_limit" class="text" size="4" value="' . $click_limit . '" /> ';
267
						/* //translators: "Show links with <more/less> than <text field> clicks" */
268
						yourls_se( 'Show links with %1$s than %2$s clicks', $_select, $_input );
269
						echo "<br/>\n";
270
271
						// Fifth search control: Show links created before/after/between ...
272
						$_options = array(
273
							'before'  => yourls__('before'),
274
							'after'   => yourls__('after'),
275
							'between' => yourls__('between'),
276
						);
277
						$_select = yourls_html_select( 'date_filter', $_options, $date_filter );
278
						$_input  = '<input type="text" name="date_first" id="date_first" class="text" size="12" value="' . $date_first . '" />';
279
						$_and    = '<span id="date_and"' . ( $date_filter === 'between' ? ' style="display:inline"' : '' ) . '> &amp; </span>';
280
						$_input2 = '<input type="text" name="date_second" id="date_second" class="text" size="12" value="' . $date_second . '"' . ( $date_filter === 'between' ? ' style="display:inline"' : '' ) . '/>';
281
						/* //translators: "Show links created <before/after/between> <date input> <"and" if applicable> <date input if applicable>" */
282
						yourls_se( 'Show links created %1$s %2$s %3$s %4$s', $_select, $_input, $_and, $_input2 );
283
						?>
284
285
						<div id="filter_buttons">
286
							<input type="submit" id="submit-sort" value="<?php yourls_e('Search'); ?>" class="button primary" />
287
							&nbsp;
288
							<input type="button" id="submit-clear-filter" value="<?php yourls_e('Clear'); ?>" class="button" onclick="window.parent.location.href = 'index.php'" />
289
						</div>
290
				
291
					</div>
292
				</form>
293
			</div>
294
			
295
			<?php
296
			// Remove empty keys from the $params array so it doesn't clutter the pagination links
297
			$params = array_filter( $params, 'yourls_return_if_not_empty_string' ); // remove empty keys
298
299
			if( isset( $search_text ) ) {
300
				$params['search'] = $search_text;
301
				unset( $params['search_text'] );
302
			}
303
			?>
304
			
305
			<div id="pagination">
306
				<span class="navigation">
307
				<?php if( $total_pages > 1 ) { ?>
308
					<span class="nav_total"><?php echo sprintf( yourls_n( '1 page', '%s pages', $total_pages ), $total_pages ); ?></span>
309
					<?php
310
					$base_page = yourls_admin_url( 'index.php' );
311
					// Pagination offsets: min( max ( zomg! ) );
312
					$p_start = max(  min( $total_pages - 4, $page - 2 ), 1 );
313
					$p_end = min( max( 5, $page + 2 ), $total_pages );
314
					if( $p_start >= 2 ) {
315
						$link = yourls_add_query_arg( array_merge( $params, array( 'page' => 1 ) ), $base_page );
316
						echo '<span class="nav_link nav_first"><a href="' . $link . '" title="' . yourls_esc_attr__('Go to First Page') . '">' . yourls__( '&laquo; First' ) . '</a></span>';
317
						echo '<span class="nav_link nav_prev"></span>';
318
					}
319
					for( $i = $p_start ; $i <= $p_end; $i++ ) {
320
						if( $i == $page ) {
321
							echo "<span class='nav_link nav_current'>$i</span>";
322 View Code Duplication
						} else {
0 ignored issues
show
This code seems to be duplicated across 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...
323
							$link = yourls_add_query_arg( array_merge( $params, array( 'page' => $i ) ), $base_page );
324
							echo '<span class="nav_link nav_goto"><a href="' . $link . '" title="' . sprintf( yourls_esc_attr( 'Page %s' ), $i ) .'">'.$i.'</a></span>';
325
						}
326
					}
327 View Code Duplication
					if( ( $p_end ) < $total_pages ) {
0 ignored issues
show
This code seems to be duplicated across 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...
328
						$link = yourls_add_query_arg( array_merge( $params, array( 'page' => $total_pages ) ), $base_page );
329
						echo '<span class="nav_link nav_next"></span>';
330
						echo '<span class="nav_link nav_last"><a href="' . $link . '" title="' . yourls_esc_attr__('Go to Last Page') . '">' . yourls__( 'Last &raquo;' ) . '</a></span>';
331
					}
332
					?>
333
				<?php } ?>
334
				</span>
335
			</div>
336
			</th>
337
		</tr>
338
		<?php yourls_do_action( 'html_tfooter' ); ?>
339
	</tfoot>
340
	<?php
341
}
342
343
/**
344
 * Return a select box
345
 *
346
 * @since 1.6
347
 *
348
 * @param string $name HTML 'name' (also use as the HTML 'id')
349
 * @param array $options array of 'value' => 'Text displayed'
350
 * @param string $selected optional 'value' from the $options array that will be highlighted
351
 * @param boolean $display false (default) to return, true to echo
352
 * @return string HTML content of the select element
353
 */
354
function yourls_html_select( $name, $options, $selected = '', $display = false ) {
355
	$html = "<select name='$name' id='$name' size='1'>\n";
356
	foreach( $options as $value => $text ) {
357
		$html .= "<option value='$value' ";
358
		$html .= $selected == $value ? ' selected="selected"' : '';
359
		$html .= ">$text</option>\n";
360
	}
361
	$html .= "</select>\n";
362
	$html  = yourls_apply_filter( 'html_select', $html, $name, $options, $selected, $display );
363
	if( $display )
364
		echo $html;
365
	return $html;
366
}
367
368
/**
369
 * Display the Quick Share box
370
 *
371
 */
372
function yourls_share_box( $longurl, $shorturl, $title = '', $text='', $shortlink_title = '', $share_title = '', $hidden = false ) {
373
	if ( $shortlink_title == '' )
374
		$shortlink_title = '<h2>' . yourls__( 'Your short link' ) . '</h2>';
375
	if ( $share_title == '' )
376
		$share_title = '<h2>' . yourls__( 'Quick Share' ) . '</h2>';
377
	
378
	// Allow plugins to short-circuit the whole function
379
	$pre = yourls_apply_filter( 'shunt_share_box', false );
380
	if ( false !== $pre )
381
		return $pre;
382
		
383
	$text   = ( $text ? '"'.$text.'" ' : '' );
384
	$title  = ( $title ? "$title " : '' );
385
	$share  = yourls_esc_textarea( $title.$text.$shorturl );
386
	$count  = 140 - strlen( $share );
387
	$hidden = ( $hidden ? 'style="display:none;"' : '' );
388
	
389
	// Allow plugins to filter all data
390
	$data = compact( 'longurl', 'shorturl', 'title', 'text', 'shortlink_title', 'share_title', 'share', 'count', 'hidden' );
391
	$data = yourls_apply_filter( 'share_box_data', $data );
392
	extract( $data );
393
	
394
	$_share = rawurlencode( $share );
395
	$_url   = rawurlencode( $shorturl );
396
	?>
397
	
398
	<div id="shareboxes" <?php echo $hidden; ?>>
399
400
		<?php yourls_do_action( 'shareboxes_before', $longurl, $shorturl, $title, $text ); ?>
401
402
		<div id="copybox" class="share">
403
		<?php echo $shortlink_title; ?>
404
			<p><input id="copylink" class="text" size="32" value="<?php echo yourls_esc_url( $shorturl ); ?>" /></p>
405
			<p><small><?php yourls_e( 'Long link' ); ?>: <a id="origlink" href="<?php echo yourls_esc_url( $longurl ); ?>"><?php echo yourls_esc_url( $longurl ); ?></a></small>
406
			<?php if( yourls_do_log_redirect() ) { ?>
407
			<br/><small><?php yourls_e( 'Stats' ); ?>: <a id="statlink" href="<?php echo yourls_esc_url( $shorturl ); ?>+"><?php echo yourls_esc_url( $shorturl ); ?>+</a></small>
408
			<input type="hidden" id="titlelink" value="<?php echo yourls_esc_attr( $title ); ?>" />
409
			<?php } ?>
410
			</p>
411
		</div>
412
413
		<?php yourls_do_action( 'shareboxes_middle', $longurl, $shorturl, $title, $text ); ?>
414
415
		<div id="sharebox" class="share">
416
			<?php echo $share_title; ?>
417
			<div id="tweet">
418
				<span id="charcount" class="hide-if-no-js"><?php echo $count; ?></span>
419
				<textarea id="tweet_body"><?php echo $share; ?></textarea>
420
			</div>
421
			<p id="share_links"><?php yourls_e( 'Share with' ); ?> 
422
				<a id="share_tw" href="http://twitter.com/home?status=<?php echo $_share; ?>" title="<?php yourls_e( 'Tweet this!' ); ?>" onclick="share('tw');return false">Twitter</a>
423
				<a id="share_fb" href="http://www.facebook.com/share.php?u=<?php echo $_url; ?>" title="<?php yourls_e( 'Share on Facebook' ); ?>" onclick="share('fb');return false;">Facebook</a>
424
				<?php
425
				yourls_do_action( 'share_links', $longurl, $shorturl, $title, $text );
426
				// Note: on the main admin page, there are no parameters passed to the sharebox when it's drawn.
427
				?>
428
			</p>
429
		</div>
430
		
431
		<?php yourls_do_action( 'shareboxes_after', $longurl, $shorturl, $title, $text ); ?>
432
	
433
	</div>
434
	
435
	<?php
436
}
437
438
/**
439
 * Die die die
440
 *
441
 */
442
function yourls_die( $message = '', $title = '', $header_code = 200 ) {
443
    yourls_do_action( 'pre_yourls_die', $message, $title, $header_code );
444
445
	yourls_status_header( $header_code );
446
	
447
	if( !yourls_did_action( 'html_head' ) ) {
448
		yourls_html_head();
449
		yourls_html_logo();
450
	}
451
	echo yourls_apply_filter( 'die_title', "<h2>$title</h2>" );
452
	echo yourls_apply_filter( 'die_message', "<p>$message</p>" );
453
    // Hook into 'yourls_die' to add more elements or messages to that page
454
	yourls_do_action( 'yourls_die' );
455
	if( !yourls_did_action( 'html_footer' ) ) {
456
		yourls_html_footer();
457
	}
458
	die();
459
}
460
461
/**
462
 * Return an "Edit" row for the main table
463
 *
464
 * @param string $keyword Keyword to edit
465
 * @return string HTML of the edit row
466
 */
467
function yourls_table_edit_row( $keyword ) {
468
	$keyword = yourls_sanitize_string( $keyword );
469
	$id = yourls_string2htmlid( $keyword ); // used as HTML #id
470
	$url = yourls_get_keyword_longurl( $keyword );
471
	$title = htmlspecialchars( yourls_get_keyword_title( $keyword ) );
472
	$safe_url = yourls_esc_attr( rawurldecode( $url ) );
473
	$safe_title = yourls_esc_attr( $title );
474
    
475
    // Make strings sprintf() safe: '%' -> '%%'
476
    $safe_url = str_replace( '%', '%%', $safe_url );
477
    $safe_title = str_replace( '%', '%%', $safe_title );
478
479
	$www = yourls_link();
480
    
481
	$nonce = yourls_create_nonce( 'edit-save_'.$id );
482
	
483
	if( $url ) {
484
		$return = <<<RETURN
485
<tr id="edit-$id" class="edit-row"><td colspan="5" class="edit-row"><strong>%s</strong>:<input type="text" id="edit-url-$id" name="edit-url-$id" value="$safe_url" class="text" size="70" /><br/><strong>%s</strong>: $www<input type="text" id="edit-keyword-$id" name="edit-keyword-$id" value="$keyword" class="text" size="10" /><br/><strong>%s</strong>: <input type="text" id="edit-title-$id" name="edit-title-$id" value="$safe_title" class="text" size="60" /></td><td colspan="1"><input type="button" id="edit-submit-$id" name="edit-submit-$id" value="%s" title="%s" class="button" onclick="edit_link_save('$id');" />&nbsp;<input type="button" id="edit-close-$id" name="edit-close-$id" value="%s" title="%s" class="button" onclick="edit_link_hide('$id');" /><input type="hidden" id="old_keyword_$id" value="$keyword"/><input type="hidden" id="nonce_$id" value="$nonce"/></td></tr>
486
RETURN;
487
		$return = sprintf( $return, yourls__( 'Long URL' ), yourls__( 'Short URL' ), yourls__( 'Title' ), yourls__( 'Save' ), yourls__( 'Save new values' ), yourls__( 'Cancel' ), yourls__( 'Cancel editing' ) );
488
	} else {
489
		$return = '<tr class="edit-row notfound"><td colspan="6" class="edit-row notfound">' . yourls__( 'Error, URL not found' ) . '</td></tr>';
490
	}
491
	
492
	$return = yourls_apply_filter( 'table_edit_row', $return, $keyword, $url, $title );
493
494
	return $return;
495
}
496
497
/**
498
 * Return an "Add" row for the main table
499
 *
500
 * @return string HTML of the edit row
501
 */
502
function yourls_table_add_row( $keyword, $url, $title = '', $ip, $clicks, $timestamp ) {
503
	$keyword  = yourls_sanitize_string( $keyword );
504
	$id       = yourls_string2htmlid( $keyword ); // used as HTML #id
505
	$shorturl = yourls_link( $keyword );
506
507
	$statlink = yourls_statlink( $keyword );
508
		
509
	$delete_link = yourls_nonce_url( 'delete-link_'.$id,
510
		yourls_add_query_arg( array( 'id' => $id, 'action' => 'delete', 'keyword' => $keyword ), yourls_admin_url( 'admin-ajax.php' ) ) 
0 ignored issues
show
yourls_add_query_arg(arr..._url('admin-ajax.php')) is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
511
	);
512
	
513
	$edit_link = yourls_nonce_url( 'edit-link_'.$id,
514
		yourls_add_query_arg( array( 'id' => $id, 'action' => 'edit', 'keyword' => $keyword ), yourls_admin_url( 'admin-ajax.php' ) ) 
0 ignored issues
show
yourls_add_query_arg(arr..._url('admin-ajax.php')) is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
515
	);
516
	
517
	// Action link buttons: the array
518
	$actions = array(
519
		'stats' => array(
520
			'href'    => $statlink,
521
			'id'      => "statlink-$id",
522
			'title'   => yourls_esc_attr__( 'Stats' ),
523
			'anchor'  => yourls__( 'Stats' ),
524
		),
525
		'share' => array(
526
			'href'    => '',
527
			'id'      => "share-button-$id",
528
			'title'   => yourls_esc_attr__( 'Share' ),
529
			'anchor'  => yourls__( 'Share' ),
530
			'onclick' => "toggle_share('$id');return false;",
531
		),
532
		'edit' => array(
533
			'href'    => $edit_link,
534
			'id'      => "edit-button-$id",
535
			'title'   => yourls_esc_attr__( 'Edit' ),
536
			'anchor'  => yourls__( 'Edit' ),
537
			'onclick' => "edit_link_display('$id');return false;",
538
		),
539
		'delete' => array(
540
			'href'    => $delete_link,
541
			'id'      => "delete-button-$id",
542
			'title'   => yourls_esc_attr__( 'Delete' ),
543
			'anchor'  => yourls__( 'Delete' ),
544
			'onclick' => "remove_link('$id');return false;",
545
		)
546
	);
547
	$actions = yourls_apply_filter( 'table_add_row_action_array', $actions );
548
	
549
	// Action link buttons: the HTML
550
	$action_links = '';
551
	foreach( $actions as $key => $action ) {
552
		$onclick = isset( $action['onclick'] ) ? 'onclick="' . $action['onclick'] . '"' : '' ;
553
		$action_links .= sprintf( '<a href="%s" id="%s" title="%s" class="%s" %s>%s</a>',
554
			$action['href'], $action['id'], $action['title'], 'button button_'.$key, $onclick, $action['anchor']
555
		);
556
	}
557
	$action_links = yourls_apply_filter( 'action_links', $action_links, $keyword, $url, $ip, $clicks, $timestamp );
558
559
	if( ! $title )
560
		$title = $url;
561
562
	$protocol_warning = '';
563
	if( ! in_array( yourls_get_protocol( $url ) , array( 'http://', 'https://' ) ) )
564
		$protocol_warning = yourls_apply_filter( 'add_row_protocol_warning', '<span class="warning" title="' . yourls__( 'Not a common link' ) . '">&#9733;</span>' );
565
566
	// Row cells: the array
567
	$cells = array(
568
		'keyword' => array(
569
			'template'      => '<a href="%shorturl%">%keyword_html%</a>',
570
			'shorturl'      => yourls_esc_url( $shorturl ),
571
			'keyword_html'  => yourls_esc_html( $keyword ),
572
		),
573
		'url' => array(
574
			'template'      => '<a href="%long_url%" title="%title_attr%">%title_html%</a><br/><small>%warning%<a href="%long_url%">%long_url_html%</a></small>',
575
			'long_url'      => yourls_esc_url( $url ),
576
			'title_attr'    => yourls_esc_attr( $title ),
577
			'title_html'    => yourls_esc_html( yourls_trim_long_string( $title ) ),
578
			'long_url_html' => yourls_esc_html( yourls_trim_long_string( $url ) ),
579
			'warning'       => $protocol_warning,
580
		),
581
		'timestamp' => array(
582
			'template' => '%date%',
583
			'date'     => date( 'M d, Y H:i', $timestamp +( YOURLS_HOURS_OFFSET * 3600 ) ),
584
		),
585
		'ip' => array(
586
			'template' => '%ip%',
587
			'ip'       => $ip,
588
		),
589
		'clicks' => array(
590
			'template' => '%clicks%',
591
			'clicks'   => yourls_number_format_i18n( $clicks, 0, '', '' ),
0 ignored issues
show
The call to yourls_number_format_i18n() has too many arguments starting with ''.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
592
		),
593
		'actions' => array(
594
			'template' => '%actions% <input type="hidden" id="keyword_%id%" value="%keyword%"/>',
595
			'actions'  => $action_links,
596
			'id'       => $id,
597
			'keyword'  => $keyword,
598
		),
599
	);
600
	$cells = yourls_apply_filter( 'table_add_row_cell_array', $cells, $keyword, $url, $title, $ip, $clicks, $timestamp );
601
	
602
	// Row cells: the HTML. Replace every %stuff% in 'template' with 'stuff' value.
603
	$row = "<tr id=\"id-$id\">";
604
	foreach( $cells as $cell_id => $elements ) {
605
		$callback = new yourls_table_add_row_callback( $elements );
606
		$row .= sprintf( '<td class="%s" id="%s">', $cell_id, $cell_id . '-' . $id );
607
		$row .= preg_replace_callback( '/%([^%]+)?%/', array( $callback, 'callback' ), $elements['template'] );
608
		// For the record, in PHP 5.3+ we don't need to introduce a class in order to pass additional parameters
609
		// to the callback function. Instead, we would have used the 'use' keyword :
610
		// $row .= preg_replace_callback( '/%([^%]+)?%/', function( $match ) use ( $elements ) { return $elements[ $match[1] ]; }, $elements['template'] );
611
		
612
		$row .= '</td>';
613
	}
614
	$row .= "</tr>";
615
	$row  = yourls_apply_filter( 'table_add_row', $row, $keyword, $url, $title, $ip, $clicks, $timestamp );
616
	
617
	return $row;
618
}
619
620
/**
621
 * Callback class for yourls_table_add_row
622
 *
623
 * See comment about PHP 5.3+ in yourls_table_add_row()
624
 *
625
 * @since 1.7
626
 */
627
class yourls_table_add_row_callback {
628
    private $elements;
629
	
630
    function __construct($elements) {
0 ignored issues
show
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...
631
		$this->elements = $elements;
632
	}
633
	
634
    function callback( $matches ) {
0 ignored issues
show
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...
635
		return $this->elements[ $matches[1] ];
636
    }
637
}
638
639
640
/**
641
 * Echo the main table head
642
 *
643
 */
644
function yourls_table_head() {
645
	$start = '<table id="main_table" class="tblSorter" cellpadding="0" cellspacing="1"><thead><tr>'."\n";
646
	echo yourls_apply_filter( 'table_head_start', $start );
647
	
648
	$cells = yourls_apply_filter( 'table_head_cells', array(
649
		'shorturl' => yourls__( 'Short URL' ),
650
		'longurl'  => yourls__( 'Original URL' ),
651
		'date'     => yourls__( 'Date' ),
652
		'ip'       => yourls__( 'IP' ),
653
		'clicks'   => yourls__( 'Clicks' ),
654
		'actions'  => yourls__( 'Actions' )
655
	) );
656
	foreach( $cells as $k => $v ) {
657
		echo "<th id='main_table_head_$k'>$v</th>\n";
658
	}
659
	
660
	$end = "</tr></thead>\n";
661
	echo yourls_apply_filter( 'table_head_end', $end );
662
}
663
664
/**
665
 * Echo the tbody start tag
666
 *
667
 */
668
function yourls_table_tbody_start() {
669
	echo yourls_apply_filter( 'table_tbody_start', '<tbody>' );
670
}
671
672
/**
673
 * Echo the tbody end tag
674
 *
675
 */
676
function yourls_table_tbody_end() {
677
	echo yourls_apply_filter( 'table_tbody_end', '</tbody>' );
678
}
679
680
/**
681
 * Echo the table start tag
682
 *
683
 */
684
function yourls_table_end() {
685
	echo yourls_apply_filter( 'table_end', '</table></main>' );
686
}
687
688
/**
689
 * Echo HTML tag for a link
690
 *
691
 */
692
function yourls_html_link( $href, $title = '', $element = '' ) {
693
	if( !$title )
694
		$title = $href;
695
	if( $element )
696
		$element = sprintf( 'id="%s"', yourls_esc_attr( $element ) );
697
	$link = sprintf( '<a href="%s" %s>%s</a>', yourls_esc_url( $href ), $element, yourls_esc_html( $title ) );
698
	echo yourls_apply_filter( 'html_link', $link );
699
}
700
701
/**
702
 * Display the login screen. Nothing past this point.
703
 *
704
 */
705
function yourls_login_screen( $error_msg = '' ) {
706
	yourls_html_head( 'login' );
707
	
708
	$action = ( isset( $_GET['action'] ) && $_GET['action'] == 'logout' ? '?' : '' );
709
710
	yourls_html_logo();
711
	?>
712
	<div id="login">
713
		<form method="post" action="<?php echo $action; ?>"> <?php // reset any QUERY parameters ?>
714
			<?php
715
				if( !empty( $error_msg ) ) {
716
					echo '<p class="error">'.$error_msg.'</p>';
717
				}
718
			?>
719
			<p>
720
				<label for="username"><?php yourls_e( 'Username' ); ?></label><br />
721
				<input type="text" id="username" name="username" size="30" class="text" />
722
			</p>
723
			<p>
724
				<label for="password"><?php yourls_e( 'Password' ); ?></label><br />
725
				<input type="password" id="password" name="password" size="30" class="text" />
726
			</p>
727
			<p style="text-align: right;">
728
				<input type="submit" id="submit" name="submit" value="<?php yourls_e( 'Login' ); ?>" class="button" />
729
			</p>
730
		</form>
731
		<script type="text/javascript">$('#username').focus();</script>
732
	</div>
733
	<?php
734
	yourls_html_footer();
735
	die();
736
}
737
738
/**
739
 * Display the admin menu
740
 *
741
 */
742
function yourls_html_menu() {
743
744
	// Build menu links
745
	if( defined( 'YOURLS_USER' ) ) {
746
		$logout_link = yourls_apply_filter( 'logout_link', sprintf( yourls__('Hello <strong>%s</strong>'), YOURLS_USER ) . ' (<a href="' . yourls_admin_url() . '?action=logout" title="' . yourls_esc_attr__( 'Logout' ) . '">' . yourls__( 'Logout' ) . '</a>)' );
747
	} else {
748
		$logout_link = yourls_apply_filter( 'logout_link', '' );
749
	}
750
	$help_link   = yourls_apply_filter( 'help_link',   '<a href="' . yourls_site_url( false ) .'/readme.html">' . yourls__( 'Help' ) . '</a>' );
751
	
752
	$admin_links    = array();
753
	$admin_sublinks = array();
754
	
755
	$admin_links['admin'] = array(
756
		'url'    => yourls_admin_url( 'index.php' ),
757
		'title'  => yourls__( 'Go to the admin interface' ),
758
		'anchor' => yourls__( 'Admin interface' )
759
	);
760
	
761
	if( yourls_is_admin() ) {
762
		$admin_links['tools'] = array(
763
			'url'    => yourls_admin_url( 'tools.php' ),
764
			'anchor' => yourls__( 'Tools' )
765
		);
766
		$admin_links['plugins'] = array(
767
			'url'    => yourls_admin_url( 'plugins.php' ),
768
			'anchor' => yourls__( 'Manage Plugins' )
769
		);
770
		$admin_sublinks['plugins'] = yourls_list_plugin_admin_pages();
771
	}
772
	
773
	$admin_links    = yourls_apply_filter( 'admin_links',    $admin_links );
774
	$admin_sublinks = yourls_apply_filter( 'admin_sublinks', $admin_sublinks );
775
	
776
	// Now output menu
777
	echo '<nav role="navigation"><ul id="admin_menu">'."\n";
778
	if ( yourls_is_private() && !empty( $logout_link ) )
779
		echo '<li id="admin_menu_logout_link">' . $logout_link .'</li>';
780
781
	foreach( (array)$admin_links as $link => $ar ) {
782 View Code Duplication
		if( isset( $ar['url'] ) ) {
0 ignored issues
show
This code seems to be duplicated across 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...
783
			$anchor = isset( $ar['anchor'] ) ? $ar['anchor'] : $link;
784
			$title  = isset( $ar['title'] ) ? 'title="' . $ar['title'] . '"' : '';
785
			printf( '<li id="admin_menu_%s_link" class="admin_menu_toplevel"><a href="%s" %s>%s</a>', $link, $ar['url'], $title, $anchor );
786
		}
787
		// Output submenu if any. TODO: clean up, too many code duplicated here
788
		if( isset( $admin_sublinks[$link] ) ) {
789
			echo "<ul>\n";
790
			foreach( $admin_sublinks[$link] as $link => $ar ) {
791 View Code Duplication
				if( isset( $ar['url'] ) ) {
0 ignored issues
show
This code seems to be duplicated across 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
					$anchor = isset( $ar['anchor'] ) ? $ar['anchor'] : $link;
793
					$title  = isset( $ar['title'] ) ? 'title="' . $ar['title'] . '"' : '';
794
					printf( '<li id="admin_menu_%s_link" class="admin_menu_sublevel admin_menu_sublevel_%s"><a href="%s" %s>%s</a>', $link, $link, $ar['url'], $title, $anchor );
795
				}
796
			}
797
			echo "</ul>\n";
798
		}
799
	}
800
	
801
	if ( isset( $help_link ) )
802
		echo '<li id="admin_menu_help_link">' . $help_link .'</li>';
803
		
804
	yourls_do_action( 'admin_menu' );
805
	echo "</ul></nav>\n";
806
	yourls_do_action( 'admin_notices' );
807
	yourls_do_action( 'admin_notice' ); // because I never remember if it's 'notices' or 'notice'
808
	/*
809
	To display a notice:
810
	$message = "<div>OMG, dude, I mean!</div>" );
811
	yourls_add_action( 'admin_notices', create_function( '', "echo '$message';" ) );
812
	*/
813
}
814
815
/**
816
 * Wrapper function to display admin notices
817
 *
818
 */
819
function yourls_add_notice( $message, $style = 'notice' ) {
820
	// Escape single quotes in $message to avoid breaking the anonymous function
821
	$message = yourls_notice_box( strtr( $message, array( "'" => "\'" ) ), $style );
822
	yourls_add_action( 'admin_notices', create_function( '', "echo '$message';" ) );
823
}
824
825
/**
826
 * Return a formatted notice
827
 *
828
 */
829
function yourls_notice_box( $message, $style = 'notice' ) {
830
	return <<<HTML
831
	<div class="$style">
832
	<p>$message</p>
833
	</div>
834
HTML;
835
}
836
837
/**
838
 * Display a page
839
 *
840
 */
841
function yourls_page( $page ) {
842
	$include = YOURLS_ABSPATH . "/pages/$page.php";
843
	if( !file_exists( $include ) ) {
844
		yourls_die( "Page '$page' not found", 'Not found', 404 );
845
	}
846
	yourls_do_action( 'pre_page', $page );
847
	include_once( $include );
848
	yourls_do_action( 'post_page', $page );
849
	die();	
850
}
851
852
/**
853
 * Display the language attributes for the HTML tag.
854
 *
855
 * Builds up a set of html attributes containing the text direction and language
856
 * information for the page. Stolen from WP.
857
 *
858
 * @since 1.6
859
 */
860
function yourls_html_language_attributes() {
861
	$attributes = array();
862
	$output = '';
0 ignored issues
show
$output 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...
863
	
864
	$attributes[] = ( yourls_is_rtl() ? 'dir="rtl"' : 'dir="ltr"' );
865
	
866
	$doctype = yourls_apply_filter( 'html_language_attributes_doctype', 'html' );
867
	// Experimental: get HTML lang from locale. Should work. Convert fr_FR -> fr-FR
868
	if ( $lang = str_replace( '_', '-', yourls_get_locale() ) ) {
869
		if( $doctype == 'xhtml' ) {
870
			$attributes[] = "xml:lang=\"$lang\"";
871
		} else {
872
			$attributes[] = "lang=\"$lang\"";
873
		}
874
	}
875
876
	$output = implode( ' ', $attributes );
877
	$output = yourls_apply_filter( 'html_language_attributes', $output );
878
	echo $output;
879
}
880
881
/**
882
 * Output translated strings used by the Javascript calendar
883
 *
884
 * @since 1.6
885
 */
886
function yourls_l10n_calendar_strings() {
887
	echo "\n<script>\n";
888
	echo "var l10n_cal_month = " . json_encode( array_values( yourls_l10n_months() ) ) . ";\n";
889
	echo "var l10n_cal_days = " . json_encode( array_values( yourls_l10n_weekday_initial() ) ) . ";\n";
890
	echo "var l10n_cal_today = \"" . yourls_esc_js( yourls__( 'Today' ) ) . "\";\n";
891
	echo "var l10n_cal_close = \"" . yourls_esc_js( yourls__( 'Close' ) ) . "\";\n";
892
	echo "</script>\n";
893
	
894
	// Dummy returns, to initialize l10n strings used in the calendar
895
	yourls__( 'Today' );
896
	yourls__( 'Close' );
897
}
898
899
900
/**
901
 * Display a notice if there is a newer version of YOURLS available
902
 *
903
 * @since 1.7
904
 */
905
function yourls_new_core_version_notice() {
906
907
	$checks = yourls_get_option( 'core_version_checks' );
908
	
909
	if( isset( $checks->last_result->latest ) AND version_compare( $checks->last_result->latest, YOURLS_VERSION, '>' ) ) {
910
		$msg = yourls_s( '<a href="%s">YOURLS version %s</a> is available. Please update!', 'http://yourls.org/download', $checks->last_result->latest );
911
		yourls_add_notice( $msg );
912
	}
913
}
914
915
/**
916
 * Send a filerable content type header
917
 *
918
 * @since 1.7
919
 * @param string $type content type ('text/html', 'application/json', ...)
920
 * @return bool whether header was sent
921
 */
922
function yourls_content_type_header( $type ) {
923
    yourls_do_action( 'content_type_header', $type );
924
	if( !headers_sent() ) {
925
		$charset = yourls_apply_filter( 'content_type_header_charset', 'utf-8' );
926
		header( "Content-Type: $type; charset=$charset" );
927
		return true;
928
	}
929
	return false;
930
}
931
932
/**
933
 * Get search text from query string variables search_protocol, search_slashes and search
934
 *
935
 * Some servers don't like query strings containing "(ht|f)tp(s)://". A javascript bit
936
 * explodes the search text into protocol, slashes and the rest (see JS function
937
 * split_search_text_before_search()) and this function glues pieces back together
938
 * See issue https://github.com/YOURLS/YOURLS/issues/1576
939
 *
940
 * @since 1.7
941
 * @return string Search string
942
 */
943
function yourls_get_search_text() {
944
	$search = '';
945
	if( isset( $_GET['search_protocol'] ) )
946
		$search .= $_GET['search_protocol'];
947
	if( isset( $_GET['search_slashes'] ) )
948
		$search .= $_GET['search_slashes'];
949
	if( isset( $_GET['search'] ) )
950
		$search .= $_GET['search'];
951
	
952
	return htmlspecialchars( trim( $search ) );
953
}
954
955
/**
956
 * Display or return HTML for a bookmarklet link
957
 *
958
 * @since 1.7.1
959
 * @param string $href    bookmarklet link (presumably minified code with "javascript:" scheme)
960
 * @param string $anchor  link anchor
961
 * @param bool   $echo    true to display, false to return the HTML
962
 * @return string         the HTML for a bookmarklet link
963
 */
964
function yourls_bookmarklet_link( $href, $anchor, $echo = true ) {
965
    $alert = yourls_esc_attr__( 'Drag to your toolbar!' );
966
    $link = <<<LINK
967
    <a href="$href" class="bookmarklet" onclick="alert('$alert');return false;">$anchor</a>
968
LINK;
969
    
970
    if( $echo )
971
        echo $link;
972
    return $link;
973
}
974
975