~canonical-sysadmins/wordpress/4.7.4

« back to all changes in this revision

Viewing changes to wp-includes/link-template.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * WordPress Link Template Functions
 
4
 *
 
5
 * @package WordPress
 
6
 * @subpackage Template
 
7
 */
 
8
 
 
9
/**
 
10
 * Display the permalink for the current post.
 
11
 *
 
12
 * @since 1.2.0
 
13
 */
 
14
function the_permalink() {
 
15
        /**
 
16
         * Filter the display of the permalink for the current post.
 
17
         *
 
18
         * @since 1.5.0
 
19
         *
 
20
         * @param string $permalink The permalink for the current post.
 
21
         */
 
22
        echo esc_url( apply_filters( 'the_permalink', get_permalink() ) );
 
23
}
 
24
 
 
25
/**
 
26
 * Retrieve trailing slash string, if blog set for adding trailing slashes.
 
27
 *
 
28
 * Conditionally adds a trailing slash if the permalink structure has a trailing
 
29
 * slash, strips the trailing slash if not. The string is passed through the
 
30
 * 'user_trailingslashit' filter. Will remove trailing slash from string, if
 
31
 * blog is not set to have them.
 
32
 *
 
33
 * @since 2.2.0
 
34
 * @uses $wp_rewrite
 
35
 *
 
36
 * @param string $string URL with or without a trailing slash.
 
37
 * @param string $type_of_url The type of URL being considered (e.g. single, category, etc) for use in the filter.
 
38
 * @return string
 
39
 */
 
40
function user_trailingslashit($string, $type_of_url = '') {
 
41
        global $wp_rewrite;
 
42
        if ( $wp_rewrite->use_trailing_slashes )
 
43
                $string = trailingslashit($string);
 
44
        else
 
45
                $string = untrailingslashit($string);
 
46
 
 
47
        /**
 
48
         * Filter the trailing slashed string, depending on whether the site is set
 
49
         * to use training slashes.
 
50
         *
 
51
         * @since 2.2.0
 
52
         *
 
53
         * @param string $string      URL with or without a trailing slash.
 
54
         * @param string $type_of_url The type of URL being considered. Accepts 'single', 'single_trackback',
 
55
         *                            'single_feed', 'single_paged', 'feed', 'category', 'page', 'year',
 
56
         *                            'month', 'day', 'paged', 'post_type_archive'.
 
57
         */
 
58
        $string = apply_filters( 'user_trailingslashit', $string, $type_of_url );
 
59
        return $string;
 
60
}
 
61
 
 
62
/**
 
63
 * Display permalink anchor for current post.
 
64
 *
 
65
 * The permalink mode title will use the post title for the 'a' element 'id'
 
66
 * attribute. The id mode uses 'post-' with the post ID for the 'id' attribute.
 
67
 *
 
68
 * @since 0.71
 
69
 *
 
70
 * @param string $mode Permalink mode can be either 'title', 'id', or default, which is 'id'.
 
71
 */
 
72
function permalink_anchor( $mode = 'id' ) {
 
73
        $post = get_post();
 
74
        switch ( strtolower( $mode ) ) {
 
75
                case 'title':
 
76
                        $title = sanitize_title( $post->post_title ) . '-' . $post->ID;
 
77
                        echo '<a id="'.$title.'"></a>';
 
78
                        break;
 
79
                case 'id':
 
80
                default:
 
81
                        echo '<a id="post-' . $post->ID . '"></a>';
 
82
                        break;
 
83
        }
 
84
}
 
85
 
 
86
/**
 
87
 * Retrieve full permalink for current post or post ID.
 
88
 *
 
89
 * This function is an alias for get_permalink().
 
90
 *
 
91
 * @since 3.9.0
 
92
 *
 
93
 * @see get_permalink()
 
94
 *
 
95
 * @param int|WP_Post $id        Optional. Post ID or post object. Default is the current post.
 
96
 * @param bool        $leavename Optional. Whether to keep post name or page name. Default false.
 
97
 * @return string|bool The permalink URL or false if post does not exist.
 
98
 */
 
99
function get_the_permalink( $id = 0, $leavename = false ) {
 
100
        return get_permalink( $id, $leavename );
 
101
}
 
102
 
 
103
/**
 
104
 * Retrieve full permalink for current post or post ID.
 
105
 *
 
106
 * @since 1.0.0
 
107
 *
 
108
 * @param int|WP_Post $id        Optional. Post ID or post object. Default current post.
 
109
 * @param bool        $leavename Optional. Whether to keep post name or page name. Default false.
 
110
 * @return string|bool The permalink URL or false if post does not exist.
 
111
 */
 
112
function get_permalink( $id = 0, $leavename = false ) {
 
113
        $rewritecode = array(
 
114
                '%year%',
 
115
                '%monthnum%',
 
116
                '%day%',
 
117
                '%hour%',
 
118
                '%minute%',
 
119
                '%second%',
 
120
                $leavename? '' : '%postname%',
 
121
                '%post_id%',
 
122
                '%category%',
 
123
                '%author%',
 
124
                $leavename? '' : '%pagename%',
 
125
        );
 
126
 
 
127
        if ( is_object($id) && isset($id->filter) && 'sample' == $id->filter ) {
 
128
                $post = $id;
 
129
                $sample = true;
 
130
        } else {
 
131
                $post = get_post($id);
 
132
                $sample = false;
 
133
        }
 
134
 
 
135
        if ( empty($post->ID) )
 
136
                return false;
 
137
 
 
138
        if ( $post->post_type == 'page' )
 
139
                return get_page_link($post, $leavename, $sample);
 
140
        elseif ( $post->post_type == 'attachment' )
 
141
                return get_attachment_link( $post, $leavename );
 
142
        elseif ( in_array($post->post_type, get_post_types( array('_builtin' => false) ) ) )
 
143
                return get_post_permalink($post, $leavename, $sample);
 
144
 
 
145
        $permalink = get_option('permalink_structure');
 
146
 
 
147
        /**
 
148
         * Filter the permalink structure for a post before token replacement occurs.
 
149
         *
 
150
         * Only applies to posts with post_type of 'post'.
 
151
         *
 
152
         * @since 3.0.0
 
153
         *
 
154
         * @param string  $permalink The site's permalink structure.
 
155
         * @param WP_Post $post      The post in question.
 
156
         * @param bool    $leavename Whether to keep the post name.
 
157
         */
 
158
        $permalink = apply_filters( 'pre_post_link', $permalink, $post, $leavename );
 
159
 
 
160
        if ( '' != $permalink && !in_array($post->post_status, array('draft', 'pending', 'auto-draft')) ) {
 
161
                $unixtime = strtotime($post->post_date);
 
162
 
 
163
                $category = '';
 
164
                if ( strpos($permalink, '%category%') !== false ) {
 
165
                        $cats = get_the_category($post->ID);
 
166
                        if ( $cats ) {
 
167
                                usort($cats, '_usort_terms_by_ID'); // order by ID
 
168
 
 
169
                                /**
 
170
                                 * Filter the category that gets used in the %category% permalink token.
 
171
                                 *
 
172
                                 * @since 3.5.0
 
173
                                 *
 
174
                                 * @param stdClass $cat  The category to use in the permalink.
 
175
                                 * @param array    $cats Array of all categories associated with the post.
 
176
                                 * @param WP_Post  $post The post in question.
 
177
                                 */
 
178
                                $category_object = apply_filters( 'post_link_category', $cats[0], $cats, $post );
 
179
 
 
180
                                $category_object = get_term( $category_object, 'category' );
 
181
                                $category = $category_object->slug;
 
182
                                if ( $parent = $category_object->parent )
 
183
                                        $category = get_category_parents($parent, false, '/', true) . $category;
 
184
                        }
 
185
                        // show default category in permalinks, without
 
186
                        // having to assign it explicitly
 
187
                        if ( empty($category) ) {
 
188
                                $default_category = get_term( get_option( 'default_category' ), 'category' );
 
189
                                $category = is_wp_error( $default_category ) ? '' : $default_category->slug;
 
190
                        }
 
191
                }
 
192
 
 
193
                $author = '';
 
194
                if ( strpos($permalink, '%author%') !== false ) {
 
195
                        $authordata = get_userdata($post->post_author);
 
196
                        $author = $authordata->user_nicename;
 
197
                }
 
198
 
 
199
                $date = explode(" ",date('Y m d H i s', $unixtime));
 
200
                $rewritereplace =
 
201
                array(
 
202
                        $date[0],
 
203
                        $date[1],
 
204
                        $date[2],
 
205
                        $date[3],
 
206
                        $date[4],
 
207
                        $date[5],
 
208
                        $post->post_name,
 
209
                        $post->ID,
 
210
                        $category,
 
211
                        $author,
 
212
                        $post->post_name,
 
213
                );
 
214
                $permalink = home_url( str_replace($rewritecode, $rewritereplace, $permalink) );
 
215
                $permalink = user_trailingslashit($permalink, 'single');
 
216
        } else { // if they're not using the fancy permalink option
 
217
                $permalink = home_url('?p=' . $post->ID);
 
218
        }
 
219
 
 
220
        /**
 
221
         * Filter the permalink for a post.
 
222
         *
 
223
         * Only applies to posts with post_type of 'post'.
 
224
         *
 
225
         * @since 1.5.0
 
226
         *
 
227
         * @param string  $permalink The post's permalink.
 
228
         * @param WP_Post $post      The post in question.
 
229
         * @param bool    $leavename Whether to keep the post name.
 
230
         */
 
231
        return apply_filters( 'post_link', $permalink, $post, $leavename );
 
232
}
 
233
 
 
234
/**
 
235
 * Retrieve the permalink for a post with a custom post type.
 
236
 *
 
237
 * @since 3.0.0
 
238
 *
 
239
 * @param int $id Optional. Post ID.
 
240
 * @param bool $leavename Optional, defaults to false. Whether to keep post name.
 
241
 * @param bool $sample Optional, defaults to false. Is it a sample permalink.
 
242
 * @return string
 
243
 */
 
244
function get_post_permalink( $id = 0, $leavename = false, $sample = false ) {
 
245
        global $wp_rewrite;
 
246
 
 
247
        $post = get_post($id);
 
248
 
 
249
        if ( is_wp_error( $post ) )
 
250
                return $post;
 
251
 
 
252
        $post_link = $wp_rewrite->get_extra_permastruct($post->post_type);
 
253
 
 
254
        $slug = $post->post_name;
 
255
 
 
256
        $draft_or_pending = isset($post->post_status) && in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
 
257
 
 
258
        $post_type = get_post_type_object($post->post_type);
 
259
 
 
260
        if ( $post_type->hierarchical ) {
 
261
                $slug = get_page_uri( $id );
 
262
        }
 
263
 
 
264
        if ( !empty($post_link) && ( !$draft_or_pending || $sample ) ) {
 
265
                if ( ! $leavename ) {
 
266
                        $post_link = str_replace("%$post->post_type%", $slug, $post_link);
 
267
                }
 
268
                $post_link = home_url( user_trailingslashit($post_link) );
 
269
        } else {
 
270
                if ( $post_type->query_var && ( isset($post->post_status) && !$draft_or_pending ) )
 
271
                        $post_link = add_query_arg($post_type->query_var, $slug, '');
 
272
                else
 
273
                        $post_link = add_query_arg(array('post_type' => $post->post_type, 'p' => $post->ID), '');
 
274
                $post_link = home_url($post_link);
 
275
        }
 
276
 
 
277
        /**
 
278
         * Filter the permalink for a post with a custom post type.
 
279
         *
 
280
         * @since 3.0.0
 
281
         *
 
282
         * @param string  $post_link The post's permalink.
 
283
         * @param WP_Post $post      The post in question.
 
284
         * @param bool    $leavename Whether to keep the post name.
 
285
         * @param bool    $sample    Is it a sample permalink.
 
286
         */
 
287
        return apply_filters( 'post_type_link', $post_link, $post, $leavename, $sample );
 
288
}
 
289
 
 
290
/**
 
291
 * Retrieve permalink from post ID.
 
292
 *
 
293
 * @since 1.0.0
 
294
 *
 
295
 * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global $post.
 
296
 * @param mixed $deprecated Not used.
 
297
 * @return string
 
298
 */
 
299
function post_permalink( $post_id = 0, $deprecated = '' ) {
 
300
        if ( !empty( $deprecated ) )
 
301
                _deprecated_argument( __FUNCTION__, '1.3' );
 
302
 
 
303
        return get_permalink($post_id);
 
304
}
 
305
 
 
306
/**
 
307
 * Retrieve the permalink for current page or page ID.
 
308
 *
 
309
 * Respects page_on_front. Use this one.
 
310
 *
 
311
 * @since 1.5.0
 
312
 *
 
313
 * @param int|object $post Optional. Post ID or object.
 
314
 * @param bool $leavename Optional, defaults to false. Whether to keep page name.
 
315
 * @param bool $sample Optional, defaults to false. Is it a sample permalink.
 
316
 * @return string
 
317
 */
 
318
function get_page_link( $post = false, $leavename = false, $sample = false ) {
 
319
        $post = get_post( $post );
 
320
 
 
321
        if ( 'page' == get_option( 'show_on_front' ) && $post->ID == get_option( 'page_on_front' ) )
 
322
                $link = home_url('/');
 
323
        else
 
324
                $link = _get_page_link( $post, $leavename, $sample );
 
325
 
 
326
        /**
 
327
         * Filter the permalink for a page.
 
328
         *
 
329
         * @since 1.5.0
 
330
         *
 
331
         * @param string $link    The page's permalink.
 
332
         * @param int    $post_id The ID of the page.
 
333
         * @param bool   $sample  Is it a sample permalink.
 
334
         */
 
335
        return apply_filters( 'page_link', $link, $post->ID, $sample );
 
336
}
 
337
 
 
338
/**
 
339
 * Retrieve the page permalink.
 
340
 *
 
341
 * Ignores page_on_front. Internal use only.
 
342
 *
 
343
 * @since 2.1.0
 
344
 * @access private
 
345
 *
 
346
 * @param int|object $post Optional. Post ID or object.
 
347
 * @param bool $leavename Optional. Leave name.
 
348
 * @param bool $sample Optional. Sample permalink.
 
349
 * @return string
 
350
 */
 
351
function _get_page_link( $post = false, $leavename = false, $sample = false ) {
 
352
        global $wp_rewrite;
 
353
 
 
354
        $post = get_post( $post );
 
355
 
 
356
        $draft_or_pending = in_array( $post->post_status, array( 'draft', 'pending', 'auto-draft' ) );
 
357
 
 
358
        $link = $wp_rewrite->get_page_permastruct();
 
359
 
 
360
        if ( !empty($link) && ( ( isset($post->post_status) && !$draft_or_pending ) || $sample ) ) {
 
361
                if ( ! $leavename ) {
 
362
                        $link = str_replace('%pagename%', get_page_uri( $post ), $link);
 
363
                }
 
364
 
 
365
                $link = home_url($link);
 
366
                $link = user_trailingslashit($link, 'page');
 
367
        } else {
 
368
                $link = home_url( '?page_id=' . $post->ID );
 
369
        }
 
370
 
 
371
        /**
 
372
         * Filter the permalink for a non-page_on_front page.
 
373
         *
 
374
         * @since 2.1.0
 
375
         *
 
376
         * @param string $link    The page's permalink.
 
377
         * @param int    $post_id The ID of the page.
 
378
         */
 
379
        return apply_filters( '_get_page_link', $link, $post->ID );
 
380
}
 
381
 
 
382
/**
 
383
 * Retrieve permalink for attachment.
 
384
 *
 
385
 * This can be used in the WordPress Loop or outside of it.
 
386
 *
 
387
 * @since 2.0.0
 
388
 *
 
389
 * @param int|object $post Optional. Post ID or object.
 
390
 * @param bool $leavename Optional. Leave name.
 
391
 * @return string
 
392
 */
 
393
function get_attachment_link( $post = null, $leavename = false ) {
 
394
        global $wp_rewrite;
 
395
 
 
396
        $link = false;
 
397
 
 
398
        $post = get_post( $post );
 
399
        $parent = ( $post->post_parent > 0 && $post->post_parent != $post->ID ) ? get_post( $post->post_parent ) : false;
 
400
 
 
401
        if ( $wp_rewrite->using_permalinks() && $parent ) {
 
402
                if ( 'page' == $parent->post_type )
 
403
                        $parentlink = _get_page_link( $post->post_parent ); // Ignores page_on_front
 
404
                else
 
405
                        $parentlink = get_permalink( $post->post_parent );
 
406
 
 
407
                if ( is_numeric($post->post_name) || false !== strpos(get_option('permalink_structure'), '%category%') )
 
408
                        $name = 'attachment/' . $post->post_name; // <permalink>/<int>/ is paged so we use the explicit attachment marker
 
409
                else
 
410
                        $name = $post->post_name;
 
411
 
 
412
                if ( strpos($parentlink, '?') === false )
 
413
                        $link = user_trailingslashit( trailingslashit($parentlink) . '%postname%' );
 
414
 
 
415
                if ( ! $leavename )
 
416
                        $link = str_replace( '%postname%', $name, $link );
 
417
        }
 
418
 
 
419
        if ( ! $link )
 
420
                $link = home_url( '/?attachment_id=' . $post->ID );
 
421
 
 
422
        /**
 
423
         * Filter the permalink for an attachment.
 
424
         *
 
425
         * @since 2.0.0
 
426
         *
 
427
         * @param string $link    The attachment's permalink.
 
428
         * @param int    $post_id Attachment ID.
 
429
         */
 
430
        return apply_filters( 'attachment_link', $link, $post->ID );
 
431
}
 
432
 
 
433
/**
 
434
 * Retrieve the permalink for the year archives.
 
435
 *
 
436
 * @since 1.5.0
 
437
 *
 
438
 * @param int|bool $year False for current year or year for permalink.
 
439
 * @return string
 
440
 */
 
441
function get_year_link($year) {
 
442
        global $wp_rewrite;
 
443
        if ( !$year )
 
444
                $year = gmdate('Y', current_time('timestamp'));
 
445
        $yearlink = $wp_rewrite->get_year_permastruct();
 
446
        if ( !empty($yearlink) ) {
 
447
                $yearlink = str_replace('%year%', $year, $yearlink);
 
448
                $yearlink = home_url( user_trailingslashit( $yearlink, 'year' ) );
 
449
        } else {
 
450
                $yearlink = home_url( '?m=' . $year );
 
451
        }
 
452
 
 
453
        /**
 
454
         * Filter the year archive permalink.
 
455
         *
 
456
         * @since 1.5.0
 
457
         *
 
458
         * @param string $yearlink Permalink for the year archive.
 
459
         * @param int    $year     Year for the archive.
 
460
         */
 
461
        return apply_filters( 'year_link', $yearlink, $year );
 
462
}
 
463
 
 
464
/**
 
465
 * Retrieve the permalink for the month archives with year.
 
466
 *
 
467
 * @since 1.0.0
 
468
 *
 
469
 * @param bool|int $year False for current year. Integer of year.
 
470
 * @param bool|int $month False for current month. Integer of month.
 
471
 * @return string
 
472
 */
 
473
function get_month_link($year, $month) {
 
474
        global $wp_rewrite;
 
475
        if ( !$year )
 
476
                $year = gmdate('Y', current_time('timestamp'));
 
477
        if ( !$month )
 
478
                $month = gmdate('m', current_time('timestamp'));
 
479
        $monthlink = $wp_rewrite->get_month_permastruct();
 
480
        if ( !empty($monthlink) ) {
 
481
                $monthlink = str_replace('%year%', $year, $monthlink);
 
482
                $monthlink = str_replace('%monthnum%', zeroise(intval($month), 2), $monthlink);
 
483
                $monthlink = home_url( user_trailingslashit( $monthlink, 'month' ) );
 
484
        } else {
 
485
                $monthlink = home_url( '?m=' . $year . zeroise( $month, 2 ) );
 
486
        }
 
487
 
 
488
        /**
 
489
         * Filter the month archive permalink.
 
490
         *
 
491
         * @since 1.5.0
 
492
         *
 
493
         * @param string $monthlink Permalink for the month archive.
 
494
         * @param int    $year      Year for the archive.
 
495
         * @param int    $month     The month for the archive.
 
496
         */
 
497
        return apply_filters( 'month_link', $monthlink, $year, $month );
 
498
}
 
499
 
 
500
/**
 
501
 * Retrieve the permalink for the day archives with year and month.
 
502
 *
 
503
 * @since 1.0.0
 
504
 *
 
505
 * @param bool|int $year False for current year. Integer of year.
 
506
 * @param bool|int $month False for current month. Integer of month.
 
507
 * @param bool|int $day False for current day. Integer of day.
 
508
 * @return string
 
509
 */
 
510
function get_day_link($year, $month, $day) {
 
511
        global $wp_rewrite;
 
512
        if ( !$year )
 
513
                $year = gmdate('Y', current_time('timestamp'));
 
514
        if ( !$month )
 
515
                $month = gmdate('m', current_time('timestamp'));
 
516
        if ( !$day )
 
517
                $day = gmdate('j', current_time('timestamp'));
 
518
 
 
519
        $daylink = $wp_rewrite->get_day_permastruct();
 
520
        if ( !empty($daylink) ) {
 
521
                $daylink = str_replace('%year%', $year, $daylink);
 
522
                $daylink = str_replace('%monthnum%', zeroise(intval($month), 2), $daylink);
 
523
                $daylink = str_replace('%day%', zeroise(intval($day), 2), $daylink);
 
524
                $daylink = home_url( user_trailingslashit( $daylink, 'day' ) );
 
525
        } else {
 
526
                $daylink = home_url( '?m=' . $year . zeroise( $month, 2 ) . zeroise( $day, 2 ) );
 
527
        }
 
528
 
 
529
        /**
 
530
         * Filter the day archive permalink.
 
531
         *
 
532
         * @since 1.5.0
 
533
         *
 
534
         * @param string $daylink Permalink for the day archive.
 
535
         * @param int    $year    Year for the archive.
 
536
         * @param int    $month   Month for the archive.
 
537
         * @param int    $day     The day for the archive.
 
538
         */
 
539
        return apply_filters( 'day_link', $daylink, $year, $month, $day );
 
540
}
 
541
 
 
542
/**
 
543
 * Display the permalink for the feed type.
 
544
 *
 
545
 * @since 3.0.0
 
546
 *
 
547
 * @param string $anchor The link's anchor text.
 
548
 * @param string $feed Optional, defaults to default feed. Feed type.
 
549
 */
 
550
function the_feed_link( $anchor, $feed = '' ) {
 
551
        $link = '<a href="' . esc_url( get_feed_link( $feed ) ) . '">' . $anchor . '</a>';
 
552
 
 
553
        /**
 
554
         * Filter the feed link anchor tag.
 
555
         *
 
556
         * @since 3.0.0
 
557
         *
 
558
         * @param string $link The complete anchor tag for a feed link.
 
559
         * @param string $feed The feed type, or an empty string for the
 
560
         *                     default feed type.
 
561
         */
 
562
        echo apply_filters( 'the_feed_link', $link, $feed );
 
563
}
 
564
 
 
565
/**
 
566
 * Retrieve the permalink for the feed type.
 
567
 *
 
568
 * @since 1.5.0
 
569
 *
 
570
 * @param string $feed Optional, defaults to default feed. Feed type.
 
571
 * @return string
 
572
 */
 
573
function get_feed_link($feed = '') {
 
574
        global $wp_rewrite;
 
575
 
 
576
        $permalink = $wp_rewrite->get_feed_permastruct();
 
577
        if ( '' != $permalink ) {
 
578
                if ( false !== strpos($feed, 'comments_') ) {
 
579
                        $feed = str_replace('comments_', '', $feed);
 
580
                        $permalink = $wp_rewrite->get_comment_feed_permastruct();
 
581
                }
 
582
 
 
583
                if ( get_default_feed() == $feed )
 
584
                        $feed = '';
 
585
 
 
586
                $permalink = str_replace('%feed%', $feed, $permalink);
 
587
                $permalink = preg_replace('#/+#', '/', "/$permalink");
 
588
                $output =  home_url( user_trailingslashit($permalink, 'feed') );
 
589
        } else {
 
590
                if ( empty($feed) )
 
591
                        $feed = get_default_feed();
 
592
 
 
593
                if ( false !== strpos($feed, 'comments_') )
 
594
                        $feed = str_replace('comments_', 'comments-', $feed);
 
595
 
 
596
                $output = home_url("?feed={$feed}");
 
597
        }
 
598
 
 
599
        /**
 
600
         * Filter the feed type permalink.
 
601
         *
 
602
         * @since 1.5.0
 
603
         *
 
604
         * @param string $output The feed permalink.
 
605
         * @param string $feed   Feed type.
 
606
         */
 
607
        return apply_filters( 'feed_link', $output, $feed );
 
608
}
 
609
 
 
610
/**
 
611
 * Retrieve the permalink for the post comments feed.
 
612
 *
 
613
 * @since 2.2.0
 
614
 *
 
615
 * @param int $post_id Optional. Post ID.
 
616
 * @param string $feed Optional. Feed type.
 
617
 * @return string
 
618
 */
 
619
function get_post_comments_feed_link($post_id = 0, $feed = '') {
 
620
        $post_id = absint( $post_id );
 
621
 
 
622
        if ( ! $post_id )
 
623
                $post_id = get_the_ID();
 
624
 
 
625
        if ( empty( $feed ) )
 
626
                $feed = get_default_feed();
 
627
 
 
628
        if ( '' != get_option('permalink_structure') ) {
 
629
                if ( 'page' == get_option('show_on_front') && $post_id == get_option('page_on_front') )
 
630
                        $url = _get_page_link( $post_id );
 
631
                else
 
632
                        $url = get_permalink($post_id);
 
633
 
 
634
                $url = trailingslashit($url) . 'feed';
 
635
                if ( $feed != get_default_feed() )
 
636
                        $url .= "/$feed";
 
637
                $url = user_trailingslashit($url, 'single_feed');
 
638
        } else {
 
639
                $type = get_post_field('post_type', $post_id);
 
640
                if ( 'page' == $type )
 
641
                        $url = add_query_arg( array( 'feed' => $feed, 'page_id' => $post_id ), home_url( '/' ) );
 
642
                else
 
643
                        $url = add_query_arg( array( 'feed' => $feed, 'p' => $post_id ), home_url( '/' ) );
 
644
        }
 
645
 
 
646
        /**
 
647
         * Filter the post comments feed permalink.
 
648
         *
 
649
         * @since 1.5.1
 
650
         *
 
651
         * @param string $url Post comments feed permalink.
 
652
         */
 
653
        return apply_filters( 'post_comments_feed_link', $url );
 
654
}
 
655
 
 
656
/**
 
657
 * Display the comment feed link for a post.
 
658
 *
 
659
 * Prints out the comment feed link for a post. Link text is placed in the
 
660
 * anchor. If no link text is specified, default text is used. If no post ID is
 
661
 * specified, the current post is used.
 
662
 *
 
663
 * @since 2.5.0
 
664
 *
 
665
 * @param string $link_text Descriptive text.
 
666
 * @param int $post_id Optional post ID. Default to current post.
 
667
 * @param string $feed Optional. Feed format.
 
668
 * @return string Link to the comment feed for the current post.
 
669
*/
 
670
function post_comments_feed_link( $link_text = '', $post_id = '', $feed = '' ) {
 
671
        $url = esc_url( get_post_comments_feed_link( $post_id, $feed ) );
 
672
        if ( empty($link_text) )
 
673
                $link_text = __('Comments Feed');
 
674
 
 
675
        /**
 
676
         * Filter the post comment feed link anchor tag.
 
677
         *
 
678
         * @since 2.8.0
 
679
         *
 
680
         * @param string $link    The complete anchor tag for the comment feed link.
 
681
         * @param int    $post_id Post ID.
 
682
         * @param string $feed    The feed type, or an empty string for the default feed type.
 
683
         */
 
684
        echo apply_filters( 'post_comments_feed_link_html', "<a href='$url'>$link_text</a>", $post_id, $feed );
 
685
}
 
686
 
 
687
/**
 
688
 * Retrieve the feed link for a given author.
 
689
 *
 
690
 * Returns a link to the feed for all posts by a given author. A specific feed
 
691
 * can be requested or left blank to get the default feed.
 
692
 *
 
693
 * @since 2.5.0
 
694
 *
 
695
 * @param int $author_id ID of an author.
 
696
 * @param string $feed Optional. Feed type.
 
697
 * @return string Link to the feed for the author specified by $author_id.
 
698
*/
 
699
function get_author_feed_link( $author_id, $feed = '' ) {
 
700
        $author_id = (int) $author_id;
 
701
        $permalink_structure = get_option('permalink_structure');
 
702
 
 
703
        if ( empty($feed) )
 
704
                $feed = get_default_feed();
 
705
 
 
706
        if ( '' == $permalink_structure ) {
 
707
                $link = home_url("?feed=$feed&amp;author=" . $author_id);
 
708
        } else {
 
709
                $link = get_author_posts_url($author_id);
 
710
                if ( $feed == get_default_feed() )
 
711
                        $feed_link = 'feed';
 
712
                else
 
713
                        $feed_link = "feed/$feed";
 
714
 
 
715
                $link = trailingslashit($link) . user_trailingslashit($feed_link, 'feed');
 
716
        }
 
717
 
 
718
        /**
 
719
         * Filter the feed link for a given author.
 
720
         *
 
721
         * @since 1.5.1
 
722
         *
 
723
         * @param string $link The author feed link.
 
724
         * @param string $feed Feed type.
 
725
         */
 
726
        $link = apply_filters( 'author_feed_link', $link, $feed );
 
727
 
 
728
        return $link;
 
729
}
 
730
 
 
731
/**
 
732
 * Retrieve the feed link for a category.
 
733
 *
 
734
 * Returns a link to the feed for all posts in a given category. A specific feed
 
735
 * can be requested or left blank to get the default feed.
 
736
 *
 
737
 * @since 2.5.0
 
738
 *
 
739
 * @param int $cat_id ID of a category.
 
740
 * @param string $feed Optional. Feed type.
 
741
 * @return string Link to the feed for the category specified by $cat_id.
 
742
*/
 
743
function get_category_feed_link($cat_id, $feed = '') {
 
744
        return get_term_feed_link($cat_id, 'category', $feed);
 
745
}
 
746
 
 
747
/**
 
748
 * Retrieve the feed link for a term.
 
749
 *
 
750
 * Returns a link to the feed for all posts in a given term. A specific feed
 
751
 * can be requested or left blank to get the default feed.
 
752
 *
 
753
 * @since 3.0.0
 
754
 *
 
755
 * @param int $term_id ID of a category.
 
756
 * @param string $taxonomy Optional. Taxonomy of $term_id
 
757
 * @param string $feed Optional. Feed type.
 
758
 * @return string Link to the feed for the term specified by $term_id and $taxonomy.
 
759
*/
 
760
function get_term_feed_link( $term_id, $taxonomy = 'category', $feed = '' ) {
 
761
        $term_id = ( int ) $term_id;
 
762
 
 
763
        $term = get_term( $term_id, $taxonomy  );
 
764
 
 
765
        if ( empty( $term ) || is_wp_error( $term ) )
 
766
                return false;
 
767
 
 
768
        if ( empty( $feed ) )
 
769
                $feed = get_default_feed();
 
770
 
 
771
        $permalink_structure = get_option( 'permalink_structure' );
 
772
 
 
773
        if ( '' == $permalink_structure ) {
 
774
                if ( 'category' == $taxonomy ) {
 
775
                        $link = home_url("?feed=$feed&amp;cat=$term_id");
 
776
                }
 
777
                elseif ( 'post_tag' == $taxonomy ) {
 
778
                        $link = home_url("?feed=$feed&amp;tag=$term->slug");
 
779
                } else {
 
780
                        $t = get_taxonomy( $taxonomy );
 
781
                        $link = home_url("?feed=$feed&amp;$t->query_var=$term->slug");
 
782
                }
 
783
        } else {
 
784
                $link = get_term_link( $term_id, $term->taxonomy );
 
785
                if ( $feed == get_default_feed() )
 
786
                        $feed_link = 'feed';
 
787
                else
 
788
                        $feed_link = "feed/$feed";
 
789
 
 
790
                $link = trailingslashit( $link ) . user_trailingslashit( $feed_link, 'feed' );
 
791
        }
 
792
 
 
793
        if ( 'category' == $taxonomy ) {
 
794
                /**
 
795
                 * Filter the category feed link.
 
796
                 *
 
797
                 * @since 1.5.1
 
798
                 *
 
799
                 * @param string $link The category feed link.
 
800
                 * @param string $feed Feed type.
 
801
                 */
 
802
                $link = apply_filters( 'category_feed_link', $link, $feed );
 
803
        } elseif ( 'post_tag' == $taxonomy ) {
 
804
                /**
 
805
                 * Filter the post tag feed link.
 
806
                 *
 
807
                 * @since 2.3.0
 
808
                 *
 
809
                 * @param string $link The tag feed link.
 
810
                 * @param string $feed Feed type.
 
811
                 */
 
812
                $link = apply_filters( 'tag_feed_link', $link, $feed );
 
813
        } else {
 
814
                /**
 
815
                 * Filter the feed link for a taxonomy other than 'category' or 'post_tag'.
 
816
                 *
 
817
                 * @since 3.0.0
 
818
                 *
 
819
                 * @param string $link The taxonomy feed link.
 
820
                 * @param string $feed Feed type.
 
821
                 * @param string $feed The taxonomy name.
 
822
                 */
 
823
                $link = apply_filters( 'taxonomy_feed_link', $link, $feed, $taxonomy );
 
824
        }
 
825
 
 
826
        return $link;
 
827
}
 
828
 
 
829
/**
 
830
 * Retrieve permalink for feed of tag.
 
831
 *
 
832
 * @since 2.3.0
 
833
 *
 
834
 * @param int $tag_id Tag ID.
 
835
 * @param string $feed Optional. Feed type.
 
836
 * @return string
 
837
 */
 
838
function get_tag_feed_link($tag_id, $feed = '') {
 
839
        return get_term_feed_link($tag_id, 'post_tag', $feed);
 
840
}
 
841
 
 
842
/**
 
843
 * Retrieve edit tag link.
 
844
 *
 
845
 * @since 2.7.0
 
846
 *
 
847
 * @param int $tag_id Tag ID
 
848
 * @param string $taxonomy Taxonomy
 
849
 * @return string
 
850
 */
 
851
function get_edit_tag_link( $tag_id, $taxonomy = 'post_tag' ) {
 
852
        /**
 
853
         * Filter the edit link for a tag (or term in another taxonomy).
 
854
         *
 
855
         * @since 2.7.0
 
856
         *
 
857
         * @param string $link The term edit link.
 
858
         */
 
859
        return apply_filters( 'get_edit_tag_link', get_edit_term_link( $tag_id, $taxonomy ) );
 
860
}
 
861
 
 
862
/**
 
863
 * Display or retrieve edit tag link with formatting.
 
864
 *
 
865
 * @since 2.7.0
 
866
 *
 
867
 * @param string $link Optional. Anchor text.
 
868
 * @param string $before Optional. Display before edit link.
 
869
 * @param string $after Optional. Display after edit link.
 
870
 * @param object $tag Tag object.
 
871
 * @return string HTML content.
 
872
 */
 
873
function edit_tag_link( $link = '', $before = '', $after = '', $tag = null ) {
 
874
        $link = edit_term_link( $link, '', '', $tag, false );
 
875
 
 
876
        /**
 
877
         * Filter the anchor tag for the edit link for a tag (or term in another taxonomy).
 
878
         *
 
879
         * @since 2.7.0
 
880
         *
 
881
         * @param string $link The anchor tag for the edit link.
 
882
         */
 
883
        echo $before . apply_filters( 'edit_tag_link', $link ) . $after;
 
884
}
 
885
 
 
886
/**
 
887
 * Retrieve edit term url.
 
888
 *
 
889
 * @since 3.1.0
 
890
 *
 
891
 * @param int $term_id Term ID
 
892
 * @param string $taxonomy Taxonomy
 
893
 * @param string $object_type The object type
 
894
 * @return string
 
895
 */
 
896
function get_edit_term_link( $term_id, $taxonomy, $object_type = '' ) {
 
897
        $tax = get_taxonomy( $taxonomy );
 
898
        if ( !current_user_can( $tax->cap->edit_terms ) )
 
899
                return;
 
900
 
 
901
        $term = get_term( $term_id, $taxonomy );
 
902
 
 
903
        $args = array(
 
904
                'action' => 'edit',
 
905
                'taxonomy' => $taxonomy,
 
906
                'tag_ID' => $term->term_id,
 
907
        );
 
908
 
 
909
        if ( $object_type )
 
910
                $args['post_type'] = $object_type;
 
911
 
 
912
        $location = add_query_arg( $args, admin_url( 'edit-tags.php' ) );
 
913
 
 
914
        /**
 
915
         * Filter the edit link for a term.
 
916
         *
 
917
         * @since 3.1.0
 
918
         *
 
919
         * @param string $location    The edit link.
 
920
         * @param int    $term_id     Term ID.
 
921
         * @param string $taxonomy    Taxonomy name.
 
922
         * @param string $object_type The object type (eg. the post type).
 
923
         */
 
924
        return apply_filters( 'get_edit_term_link', $location, $term_id, $taxonomy, $object_type );
 
925
}
 
926
 
 
927
/**
 
928
 * Display or retrieve edit term link with formatting.
 
929
 *
 
930
 * @since 3.1.0
 
931
 *
 
932
 * @param string $link Optional. Anchor text.
 
933
 * @param string $before Optional. Display before edit link.
 
934
 * @param string $after Optional. Display after edit link.
 
935
 * @param object $term Term object.
 
936
 * @return string HTML content.
 
937
 */
 
938
function edit_term_link( $link = '', $before = '', $after = '', $term = null, $echo = true ) {
 
939
        if ( is_null( $term ) )
 
940
                $term = get_queried_object();
 
941
 
 
942
        if ( ! $term )
 
943
                return;
 
944
 
 
945
        $tax = get_taxonomy( $term->taxonomy );
 
946
        if ( ! current_user_can( $tax->cap->edit_terms ) )
 
947
                return;
 
948
 
 
949
        if ( empty( $link ) )
 
950
                $link = __('Edit This');
 
951
 
 
952
        $link = '<a href="' . get_edit_term_link( $term->term_id, $term->taxonomy ) . '">' . $link . '</a>';
 
953
 
 
954
        /**
 
955
         * Filter the anchor tag for the edit link of a term.
 
956
         *
 
957
         * @since 3.1.0
 
958
         *
 
959
         * @param string $link    The anchor tag for the edit link.
 
960
         * @param int    $term_id Term ID.
 
961
         */
 
962
        $link = $before . apply_filters( 'edit_term_link', $link, $term->term_id ) . $after;
 
963
 
 
964
        if ( $echo )
 
965
                echo $link;
 
966
        else
 
967
                return $link;
 
968
}
 
969
 
 
970
/**
 
971
 * Retrieve permalink for search.
 
972
 *
 
973
 * @since  3.0.0
 
974
 *
 
975
 * @param string $query Optional. The query string to use. If empty the current query is used.
 
976
 * @return string
 
977
 */
 
978
function get_search_link( $query = '' ) {
 
979
        global $wp_rewrite;
 
980
 
 
981
        if ( empty($query) )
 
982
                $search = get_search_query( false );
 
983
        else
 
984
                $search = stripslashes($query);
 
985
 
 
986
        $permastruct = $wp_rewrite->get_search_permastruct();
 
987
 
 
988
        if ( empty( $permastruct ) ) {
 
989
                $link = home_url('?s=' . urlencode($search) );
 
990
        } else {
 
991
                $search = urlencode($search);
 
992
                $search = str_replace('%2F', '/', $search); // %2F(/) is not valid within a URL, send it unencoded.
 
993
                $link = str_replace( '%search%', $search, $permastruct );
 
994
                $link = home_url( user_trailingslashit( $link, 'search' ) );
 
995
        }
 
996
 
 
997
        /**
 
998
         * Filter the search permalink.
 
999
         *
 
1000
         * @since 3.0.0
 
1001
         *
 
1002
         * @param string $link   Search permalink.
 
1003
         * @param string $search The URL-encoded search term.
 
1004
         */
 
1005
        return apply_filters( 'search_link', $link, $search );
 
1006
}
 
1007
 
 
1008
/**
 
1009
 * Retrieve the permalink for the feed of the search results.
 
1010
 *
 
1011
 * @since 2.5.0
 
1012
 *
 
1013
 * @param string $search_query Optional. Search query.
 
1014
 * @param string $feed Optional. Feed type.
 
1015
 * @return string
 
1016
 */
 
1017
function get_search_feed_link($search_query = '', $feed = '') {
 
1018
        global $wp_rewrite;
 
1019
        $link = get_search_link($search_query);
 
1020
 
 
1021
        if ( empty($feed) )
 
1022
                $feed = get_default_feed();
 
1023
 
 
1024
        $permastruct = $wp_rewrite->get_search_permastruct();
 
1025
 
 
1026
        if ( empty($permastruct) ) {
 
1027
                $link = add_query_arg('feed', $feed, $link);
 
1028
        } else {
 
1029
                $link = trailingslashit($link);
 
1030
                $link .= "feed/$feed/";
 
1031
        }
 
1032
 
 
1033
        /**
 
1034
         * Filter the search feed link.
 
1035
         *
 
1036
         * @since 2.5.0
 
1037
         *
 
1038
         * @param string $link Search feed link.
 
1039
         * @param string $feed Feed type.
 
1040
         * @param string $type The search type. One of 'posts' or 'comments'.
 
1041
         */
 
1042
        $link = apply_filters( 'search_feed_link', $link, $feed, 'posts' );
 
1043
 
 
1044
        return $link;
 
1045
}
 
1046
 
 
1047
/**
 
1048
 * Retrieve the permalink for the comments feed of the search results.
 
1049
 *
 
1050
 * @since 2.5.0
 
1051
 *
 
1052
 * @param string $search_query Optional. Search query.
 
1053
 * @param string $feed Optional. Feed type.
 
1054
 * @return string
 
1055
 */
 
1056
function get_search_comments_feed_link($search_query = '', $feed = '') {
 
1057
        global $wp_rewrite;
 
1058
 
 
1059
        if ( empty($feed) )
 
1060
                $feed = get_default_feed();
 
1061
 
 
1062
        $link = get_search_feed_link($search_query, $feed);
 
1063
 
 
1064
        $permastruct = $wp_rewrite->get_search_permastruct();
 
1065
 
 
1066
        if ( empty($permastruct) )
 
1067
                $link = add_query_arg('feed', 'comments-' . $feed, $link);
 
1068
        else
 
1069
                $link = add_query_arg('withcomments', 1, $link);
 
1070
 
 
1071
        /** This filter is documented in wp-includes/link-template.php */
 
1072
        $link = apply_filters('search_feed_link', $link, $feed, 'comments');
 
1073
 
 
1074
        return $link;
 
1075
}
 
1076
 
 
1077
/**
 
1078
 * Retrieve the permalink for a post type archive.
 
1079
 *
 
1080
 * @since 3.1.0
 
1081
 *
 
1082
 * @param string $post_type Post type
 
1083
 * @return string
 
1084
 */
 
1085
function get_post_type_archive_link( $post_type ) {
 
1086
        global $wp_rewrite;
 
1087
        if ( ! $post_type_obj = get_post_type_object( $post_type ) )
 
1088
                return false;
 
1089
 
 
1090
        if ( ! $post_type_obj->has_archive )
 
1091
                return false;
 
1092
 
 
1093
        if ( get_option( 'permalink_structure' ) && is_array( $post_type_obj->rewrite ) ) {
 
1094
                $struct = ( true === $post_type_obj->has_archive ) ? $post_type_obj->rewrite['slug'] : $post_type_obj->has_archive;
 
1095
                if ( $post_type_obj->rewrite['with_front'] )
 
1096
                        $struct = $wp_rewrite->front . $struct;
 
1097
                else
 
1098
                        $struct = $wp_rewrite->root . $struct;
 
1099
                $link = home_url( user_trailingslashit( $struct, 'post_type_archive' ) );
 
1100
        } else {
 
1101
                $link = home_url( '?post_type=' . $post_type );
 
1102
        }
 
1103
 
 
1104
        /**
 
1105
         * Filter the post type archive permalink.
 
1106
         *
 
1107
         * @since 3.1.0
 
1108
         *
 
1109
         * @param string $link      The post type archive permalink.
 
1110
         * @param string $post_type Post type name.
 
1111
         */
 
1112
        return apply_filters( 'post_type_archive_link', $link, $post_type );
 
1113
}
 
1114
 
 
1115
/**
 
1116
 * Retrieve the permalink for a post type archive feed.
 
1117
 *
 
1118
 * @since 3.1.0
 
1119
 *
 
1120
 * @param string $post_type Post type
 
1121
 * @param string $feed Optional. Feed type
 
1122
 * @return string
 
1123
 */
 
1124
function get_post_type_archive_feed_link( $post_type, $feed = '' ) {
 
1125
        $default_feed = get_default_feed();
 
1126
        if ( empty( $feed ) )
 
1127
                $feed = $default_feed;
 
1128
 
 
1129
        if ( ! $link = get_post_type_archive_link( $post_type ) )
 
1130
                return false;
 
1131
 
 
1132
        $post_type_obj = get_post_type_object( $post_type );
 
1133
        if ( get_option( 'permalink_structure' ) && is_array( $post_type_obj->rewrite ) && $post_type_obj->rewrite['feeds'] ) {
 
1134
                $link = trailingslashit( $link );
 
1135
                $link .= 'feed/';
 
1136
                if ( $feed != $default_feed )
 
1137
                        $link .= "$feed/";
 
1138
        } else {
 
1139
                $link = add_query_arg( 'feed', $feed, $link );
 
1140
        }
 
1141
 
 
1142
        /**
 
1143
         * Filter the post type archive feed link.
 
1144
         *
 
1145
         * @since 3.1.0
 
1146
         *
 
1147
         * @param string $link The post type archive feed link.
 
1148
         * @param string $feed Feed type.
 
1149
         */
 
1150
        return apply_filters( 'post_type_archive_feed_link', $link, $feed );
 
1151
}
 
1152
 
 
1153
/**
 
1154
 * Retrieve edit posts link for post.
 
1155
 *
 
1156
 * Can be used within the WordPress loop or outside of it. Can be used with
 
1157
 * pages, posts, attachments, and revisions.
 
1158
 *
 
1159
 * @since 2.3.0
 
1160
 *
 
1161
 * @param int $id Optional. Post ID.
 
1162
 * @param string $context Optional, defaults to display. How to write the '&', defaults to '&amp;'.
 
1163
 * @return string
 
1164
 */
 
1165
function get_edit_post_link( $id = 0, $context = 'display' ) {
 
1166
        if ( ! $post = get_post( $id ) )
 
1167
                return;
 
1168
 
 
1169
        if ( 'revision' === $post->post_type )
 
1170
                $action = '';
 
1171
        elseif ( 'display' == $context )
 
1172
                $action = '&amp;action=edit';
 
1173
        else
 
1174
                $action = '&action=edit';
 
1175
 
 
1176
        $post_type_object = get_post_type_object( $post->post_type );
 
1177
        if ( !$post_type_object )
 
1178
                return;
 
1179
 
 
1180
        if ( !current_user_can( 'edit_post', $post->ID ) )
 
1181
                return;
 
1182
 
 
1183
        /**
 
1184
         * Filter the post edit link.
 
1185
         *
 
1186
         * @since 2.3.0
 
1187
         *
 
1188
         * @param string $link    The edit link.
 
1189
         * @param int    $post_id Post ID.
 
1190
         * @param string $context The link context. If set to 'display' then ampersands
 
1191
         *                        are encoded.
 
1192
         */
 
1193
        return apply_filters( 'get_edit_post_link', admin_url( sprintf( $post_type_object->_edit_link . $action, $post->ID ) ), $post->ID, $context );
 
1194
}
 
1195
 
 
1196
/**
 
1197
 * Display edit post link for post.
 
1198
 *
 
1199
 * @since 1.0.0
 
1200
 *
 
1201
 * @param string $text Optional. Anchor text.
 
1202
 * @param string $before Optional. Display before edit link.
 
1203
 * @param string $after Optional. Display after edit link.
 
1204
 * @param int $id Optional. Post ID.
 
1205
 */
 
1206
function edit_post_link( $text = null, $before = '', $after = '', $id = 0 ) {
 
1207
        if ( ! $post = get_post( $id ) ) {
 
1208
                return;
 
1209
        }
 
1210
 
 
1211
        if ( ! $url = get_edit_post_link( $post->ID ) ) {
 
1212
                return;
 
1213
        }
 
1214
 
 
1215
        if ( null === $text ) {
 
1216
                $text = __( 'Edit This' );
 
1217
        }
 
1218
 
 
1219
        $link = '<a class="post-edit-link" href="' . $url . '">' . $text . '</a>';
 
1220
 
 
1221
        /**
 
1222
         * Filter the post edit link anchor tag.
 
1223
         *
 
1224
         * @since 2.3.0
 
1225
         *
 
1226
         * @param string $link    Anchor tag for the edit link.
 
1227
         * @param int    $post_id Post ID.
 
1228
         * @param string $text    Anchor text.
 
1229
         */
 
1230
        echo $before . apply_filters( 'edit_post_link', $link, $post->ID, $text ) . $after;
 
1231
}
 
1232
 
 
1233
/**
 
1234
 * Retrieve delete posts link for post.
 
1235
 *
 
1236
 * Can be used within the WordPress loop or outside of it, with any post type.
 
1237
 *
 
1238
 * @since 2.9.0
 
1239
 *
 
1240
 * @param int $id Optional. Post ID.
 
1241
 * @param string $deprecated Not used.
 
1242
 * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
 
1243
 * @return string
 
1244
 */
 
1245
function get_delete_post_link( $id = 0, $deprecated = '', $force_delete = false ) {
 
1246
        if ( ! empty( $deprecated ) )
 
1247
                _deprecated_argument( __FUNCTION__, '3.0' );
 
1248
 
 
1249
        if ( !$post = get_post( $id ) )
 
1250
                return;
 
1251
 
 
1252
        $post_type_object = get_post_type_object( $post->post_type );
 
1253
        if ( !$post_type_object )
 
1254
                return;
 
1255
 
 
1256
        if ( !current_user_can( 'delete_post', $post->ID ) )
 
1257
                return;
 
1258
 
 
1259
        $action = ( $force_delete || !EMPTY_TRASH_DAYS ) ? 'delete' : 'trash';
 
1260
 
 
1261
        $delete_link = add_query_arg( 'action', $action, admin_url( sprintf( $post_type_object->_edit_link, $post->ID ) ) );
 
1262
 
 
1263
        /**
 
1264
         * Filter the post delete link.
 
1265
         *
 
1266
         * @since 2.9.0
 
1267
         *
 
1268
         * @param string $link         The delete link.
 
1269
         * @param int    $post_id      Post ID.
 
1270
         * @param bool   $force_delete Whether to bypass the trash and force deletion. Default false.
 
1271
         */
 
1272
        return apply_filters( 'get_delete_post_link', wp_nonce_url( $delete_link, "$action-post_{$post->ID}" ), $post->ID, $force_delete );
 
1273
}
 
1274
 
 
1275
/**
 
1276
 * Retrieve edit comment link.
 
1277
 *
 
1278
 * @since 2.3.0
 
1279
 *
 
1280
 * @param int $comment_id Optional. Comment ID.
 
1281
 * @return string
 
1282
 */
 
1283
function get_edit_comment_link( $comment_id = 0 ) {
 
1284
        $comment = get_comment( $comment_id );
 
1285
 
 
1286
        if ( !current_user_can( 'edit_comment', $comment->comment_ID ) )
 
1287
                return;
 
1288
 
 
1289
        $location = admin_url('comment.php?action=editcomment&amp;c=') . $comment->comment_ID;
 
1290
 
 
1291
        /**
 
1292
         * Filter the comment edit link.
 
1293
         *
 
1294
         * @since 2.3.0
 
1295
         *
 
1296
         * @param string $location The edit link.
 
1297
         */
 
1298
        return apply_filters( 'get_edit_comment_link', $location );
 
1299
}
 
1300
 
 
1301
/**
 
1302
 * Display edit comment link with formatting.
 
1303
 *
 
1304
 * @since 1.0.0
 
1305
 *
 
1306
 * @param string $text Optional. Anchor text.
 
1307
 * @param string $before Optional. Display before edit link.
 
1308
 * @param string $after Optional. Display after edit link.
 
1309
 */
 
1310
function edit_comment_link( $text = null, $before = '', $after = '' ) {
 
1311
        global $comment;
 
1312
 
 
1313
        if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) ) {
 
1314
                return;
 
1315
        }
 
1316
 
 
1317
        if ( null === $text ) {
 
1318
                $text = __( 'Edit This' );
 
1319
        }
 
1320
 
 
1321
        $link = '<a class="comment-edit-link" href="' . get_edit_comment_link( $comment->comment_ID ) . '">' . $text . '</a>';
 
1322
 
 
1323
        /**
 
1324
         * Filter the comment edit link anchor tag.
 
1325
         *
 
1326
         * @since 2.3.0
 
1327
         *
 
1328
         * @param string $link       Anchor tag for the edit link.
 
1329
         * @param int    $comment_id Comment ID.
 
1330
         * @param string $text       Anchor text.
 
1331
         */
 
1332
        echo $before . apply_filters( 'edit_comment_link', $link, $comment->comment_ID, $text ) . $after;
 
1333
}
 
1334
 
 
1335
/**
 
1336
 * Display edit bookmark (literally a URL external to blog) link.
 
1337
 *
 
1338
 * @since 2.7.0
 
1339
 *
 
1340
 * @param int $link Optional. Bookmark ID.
 
1341
 * @return string
 
1342
 */
 
1343
function get_edit_bookmark_link( $link = 0 ) {
 
1344
        $link = get_bookmark( $link );
 
1345
 
 
1346
        if ( !current_user_can('manage_links') )
 
1347
                return;
 
1348
 
 
1349
        $location = admin_url('link.php?action=edit&amp;link_id=') . $link->link_id;
 
1350
 
 
1351
        /**
 
1352
         * Filter the bookmark (link) edit link.
 
1353
         *
 
1354
         * @since 2.7.0
 
1355
         *
 
1356
         * @param string $location The edit link.
 
1357
         * @param int    $link_id  Bookmark ID.
 
1358
         */
 
1359
        return apply_filters( 'get_edit_bookmark_link', $location, $link->link_id );
 
1360
}
 
1361
 
 
1362
/**
 
1363
 * Display edit bookmark (literally a URL external to blog) link anchor content.
 
1364
 *
 
1365
 * @since 2.7.0
 
1366
 *
 
1367
 * @param string $link Optional. Anchor text.
 
1368
 * @param string $before Optional. Display before edit link.
 
1369
 * @param string $after Optional. Display after edit link.
 
1370
 * @param int $bookmark Optional. Bookmark ID.
 
1371
 */
 
1372
function edit_bookmark_link( $link = '', $before = '', $after = '', $bookmark = null ) {
 
1373
        $bookmark = get_bookmark($bookmark);
 
1374
 
 
1375
        if ( !current_user_can('manage_links') )
 
1376
                return;
 
1377
 
 
1378
        if ( empty($link) )
 
1379
                $link = __('Edit This');
 
1380
 
 
1381
        $link = '<a href="' . get_edit_bookmark_link( $bookmark ) . '">' . $link . '</a>';
 
1382
 
 
1383
        /**
 
1384
         * Filter the bookmark edit link anchor tag.
 
1385
         *
 
1386
         * @since 2.7.0
 
1387
         *
 
1388
         * @param string $link    Anchor tag for the edit link.
 
1389
         * @param int    $link_id Bookmark ID.
 
1390
         */
 
1391
        echo $before . apply_filters( 'edit_bookmark_link', $link, $bookmark->link_id ) . $after;
 
1392
}
 
1393
 
 
1394
/**
 
1395
 * Retrieve edit user link
 
1396
 *
 
1397
 * @since 3.5.0
 
1398
 *
 
1399
 * @param int $user_id Optional. User ID. Defaults to the current user.
 
1400
 * @return string URL to edit user page or empty string.
 
1401
 */
 
1402
function get_edit_user_link( $user_id = null ) {
 
1403
        if ( ! $user_id )
 
1404
                $user_id = get_current_user_id();
 
1405
 
 
1406
        if ( empty( $user_id ) || ! current_user_can( 'edit_user', $user_id ) )
 
1407
                return '';
 
1408
 
 
1409
        $user = get_userdata( $user_id );
 
1410
 
 
1411
        if ( ! $user )
 
1412
                return '';
 
1413
 
 
1414
        if ( get_current_user_id() == $user->ID )
 
1415
                $link = get_edit_profile_url( $user->ID );
 
1416
        else
 
1417
                $link = add_query_arg( 'user_id', $user->ID, self_admin_url( 'user-edit.php' ) );
 
1418
 
 
1419
        /**
 
1420
         * Filter the user edit link.
 
1421
         *
 
1422
         * @since 3.5.0
 
1423
         *
 
1424
         * @param string $link    The edit link.
 
1425
         * @param int    $user_id User ID.
 
1426
         */
 
1427
        return apply_filters( 'get_edit_user_link', $link, $user->ID );
 
1428
}
 
1429
 
 
1430
// Navigation links
 
1431
 
 
1432
/**
 
1433
 * Retrieve previous post that is adjacent to current post.
 
1434
 *
 
1435
 * @since 1.5.0
 
1436
 *
 
1437
 * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term.
 
1438
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1439
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1440
 * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
 
1441
 */
 
1442
function get_previous_post( $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1443
        return get_adjacent_post( $in_same_term, $excluded_terms, true, $taxonomy );
 
1444
}
 
1445
 
 
1446
/**
 
1447
 * Retrieve next post that is adjacent to current post.
 
1448
 *
 
1449
 * @since 1.5.0
 
1450
 *
 
1451
 * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term.
 
1452
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1453
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1454
 * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
 
1455
 */
 
1456
function get_next_post( $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1457
        return get_adjacent_post( $in_same_term, $excluded_terms, false, $taxonomy );
 
1458
}
 
1459
 
 
1460
/**
 
1461
 * Retrieve adjacent post.
 
1462
 *
 
1463
 * Can either be next or previous post.
 
1464
 *
 
1465
 * @since 2.5.0
 
1466
 *
 
1467
 * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term.
 
1468
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1469
 * @param bool         $previous       Optional. Whether to retrieve previous post.
 
1470
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1471
 * @return mixed       Post object if successful. Null if global $post is not set. Empty string if no corresponding post exists.
 
1472
 */
 
1473
function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
 
1474
        global $wpdb;
 
1475
 
 
1476
        if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
 
1477
                return null;
 
1478
 
 
1479
        $current_post_date = $post->post_date;
 
1480
 
 
1481
        $join = '';
 
1482
        $where = '';
 
1483
 
 
1484
        if ( $in_same_term || ! empty( $excluded_terms ) ) {
 
1485
                $join = " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
 
1486
                $where = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy );
 
1487
 
 
1488
                if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) {
 
1489
                        // back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and "
 
1490
                        if ( false !== strpos( $excluded_terms, ' and ' ) ) {
 
1491
                                _deprecated_argument( __FUNCTION__, '3.3', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) );
 
1492
                                $excluded_terms = explode( ' and ', $excluded_terms );
 
1493
                        } else {
 
1494
                                $excluded_terms = explode( ',', $excluded_terms );
 
1495
                        }
 
1496
 
 
1497
                        $excluded_terms = array_map( 'intval', $excluded_terms );
 
1498
                }
 
1499
 
 
1500
                if ( $in_same_term ) {
 
1501
                        if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) )
 
1502
                                return '';
 
1503
                        $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
 
1504
 
 
1505
                        // Remove any exclusions from the term array to include.
 
1506
                        $term_array = array_diff( $term_array, (array) $excluded_terms );
 
1507
                        $term_array = array_map( 'intval', $term_array );
 
1508
 
 
1509
                        if ( ! $term_array || is_wp_error( $term_array ) )
 
1510
                                return '';
 
1511
 
 
1512
                        $where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")";
 
1513
                }
 
1514
 
 
1515
                if ( ! empty( $excluded_terms ) ) {
 
1516
                        $where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( $excluded_terms, ',' ) . ') )';
 
1517
                }
 
1518
        }
 
1519
 
 
1520
        $adjacent = $previous ? 'previous' : 'next';
 
1521
        $op = $previous ? '<' : '>';
 
1522
        $order = $previous ? 'DESC' : 'ASC';
 
1523
 
 
1524
        /**
 
1525
         * Filter the JOIN clause in the SQL for an adjacent post query.
 
1526
         *
 
1527
         * The dynamic portion of the hook name, $adjacent, refers to the type
 
1528
         * of adjacency, 'next' or 'previous'.
 
1529
         *
 
1530
         * @since 2.5.0
 
1531
         *
 
1532
         * @param string $join           The JOIN clause in the SQL.
 
1533
         * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
 
1534
         * @param array  $excluded_terms Array of excluded term IDs.
 
1535
         */
 
1536
        $join  = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_term, $excluded_terms );
 
1537
 
 
1538
        /**
 
1539
         * Filter the WHERE clause in the SQL for an adjacent post query.
 
1540
         *
 
1541
         * The dynamic portion of the hook name, $adjacent, refers to the type
 
1542
         * of adjacency, 'next' or 'previous'.
 
1543
         *
 
1544
         * @since 2.5.0
 
1545
         *
 
1546
         * @param string $where          The WHERE clause in the SQL.
 
1547
         * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
 
1548
         * @param array  $excluded_terms Array of excluded term IDs.
 
1549
         */
 
1550
        $where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s AND p.post_status = 'publish' $where", $current_post_date, $post->post_type ), $in_same_term, $excluded_terms );
 
1551
 
 
1552
        /**
 
1553
         * Filter the ORDER BY clause in the SQL for an adjacent post query.
 
1554
         *
 
1555
         * The dynamic portion of the hook name, $adjacent, refers to the type
 
1556
         * of adjacency, 'next' or 'previous'.
 
1557
         *
 
1558
         * @since 2.5.0
 
1559
         *
 
1560
         * @param string $order_by The ORDER BY clause in the SQL.
 
1561
         */
 
1562
        $sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1" );
 
1563
 
 
1564
        $query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
 
1565
        $query_key = 'adjacent_post_' . md5( $query );
 
1566
        $result = wp_cache_get( $query_key, 'counts' );
 
1567
        if ( false !== $result ) {
 
1568
                if ( $result )
 
1569
                        $result = get_post( $result );
 
1570
                return $result;
 
1571
        }
 
1572
 
 
1573
        $result = $wpdb->get_var( $query );
 
1574
        if ( null === $result )
 
1575
                $result = '';
 
1576
 
 
1577
        wp_cache_set( $query_key, $result, 'counts' );
 
1578
 
 
1579
        if ( $result )
 
1580
                $result = get_post( $result );
 
1581
 
 
1582
        return $result;
 
1583
}
 
1584
 
 
1585
/**
 
1586
 * Get adjacent post relational link.
 
1587
 *
 
1588
 * Can either be next or previous post relational link.
 
1589
 *
 
1590
 * @since 2.8.0
 
1591
 *
 
1592
 * @param string       $title          Optional. Link title format.
 
1593
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1594
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1595
 * @param bool         $previous       Optional. Whether to display link to previous or next post. Default true.
 
1596
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1597
 * @return string
 
1598
 */
 
1599
function get_adjacent_post_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
 
1600
        if ( $previous && is_attachment() && $post = get_post() )
 
1601
                $post = get_post( $post->post_parent );
 
1602
        else
 
1603
                $post = get_adjacent_post( $in_same_term, $excluded_terms, $previous, $taxonomy );
 
1604
 
 
1605
        if ( empty( $post ) )
 
1606
                return;
 
1607
 
 
1608
        $post_title = the_title_attribute( array( 'echo' => false, 'post' => $post ) );
 
1609
 
 
1610
        if ( empty( $post_title ) )
 
1611
                $post_title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
 
1612
 
 
1613
        $date = mysql2date( get_option( 'date_format' ), $post->post_date );
 
1614
 
 
1615
        $title = str_replace( '%title', $post_title, $title );
 
1616
        $title = str_replace( '%date', $date, $title );
 
1617
 
 
1618
        $link = $previous ? "<link rel='prev' title='" : "<link rel='next' title='";
 
1619
        $link .= esc_attr( $title );
 
1620
        $link .= "' href='" . get_permalink( $post ) . "' />\n";
 
1621
 
 
1622
        $adjacent = $previous ? 'previous' : 'next';
 
1623
 
 
1624
        /**
 
1625
         * Filter the adjacent post relational link.
 
1626
         *
 
1627
         * The dynamic portion of the hook name, $adjacent, refers to the type
 
1628
         * of adjacency, 'next' or 'previous'.
 
1629
         *
 
1630
         * @since 2.8.0
 
1631
         *
 
1632
         * @param string $link The relational link.
 
1633
         */
 
1634
        return apply_filters( "{$adjacent}_post_rel_link", $link );
 
1635
}
 
1636
 
 
1637
/**
 
1638
 * Display relational links for the posts adjacent to the current post.
 
1639
 *
 
1640
 * @since 2.8.0
 
1641
 *
 
1642
 * @param string       $title          Optional. Link title format.
 
1643
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1644
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1645
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1646
 */
 
1647
function adjacent_posts_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1648
        echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, true, $taxonomy );
 
1649
        echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, false, $taxonomy );
 
1650
}
 
1651
 
 
1652
/**
 
1653
 * Display relational links for the posts adjacent to the current post for single post pages.
 
1654
 *
 
1655
 * This is meant to be attached to actions like 'wp_head'. Do not call this directly in plugins or theme templates.
 
1656
 * @since 3.0.0
 
1657
 *
 
1658
 */
 
1659
function adjacent_posts_rel_link_wp_head() {
 
1660
        if ( ! is_single() || is_attachment() ) {
 
1661
                return;
 
1662
        }
 
1663
        adjacent_posts_rel_link();
 
1664
}
 
1665
 
 
1666
/**
 
1667
 * Display relational link for the next post adjacent to the current post.
 
1668
 *
 
1669
 * @since 2.8.0
 
1670
 *
 
1671
 * @param string       $title          Optional. Link title format.
 
1672
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1673
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1674
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1675
 */
 
1676
function next_post_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1677
        echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, false, $taxonomy );
 
1678
}
 
1679
 
 
1680
/**
 
1681
 * Display relational link for the previous post adjacent to the current post.
 
1682
 *
 
1683
 * @since 2.8.0
 
1684
 *
 
1685
 * @param string       $title          Optional. Link title format.
 
1686
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1687
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default true.
 
1688
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1689
 */
 
1690
function prev_post_rel_link( $title = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1691
        echo get_adjacent_post_rel_link( $title, $in_same_term, $excluded_terms, true, $taxonomy );
 
1692
}
 
1693
 
 
1694
/**
 
1695
 * Retrieve boundary post.
 
1696
 *
 
1697
 * Boundary being either the first or last post by publish date within the constraints specified
 
1698
 * by $in_same_term or $excluded_terms.
 
1699
 *
 
1700
 * @since 2.8.0
 
1701
 *
 
1702
 * @param bool         $in_same_term   Optional. Whether returned post should be in a same taxonomy term.
 
1703
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1704
 * @param bool         $start          Optional. Whether to retrieve first or last post.
 
1705
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1706
 * @return mixed Array containing the boundary post object if successful, null otherwise.
 
1707
 */
 
1708
function get_boundary_post( $in_same_term = false, $excluded_terms = '', $start = true, $taxonomy = 'category' ) {
 
1709
        $post = get_post();
 
1710
        if ( ! $post || ! is_single() || is_attachment() || ! taxonomy_exists( $taxonomy ) )
 
1711
                return null;
 
1712
 
 
1713
        $query_args = array(
 
1714
                'posts_per_page' => 1,
 
1715
                'order' => $start ? 'ASC' : 'DESC',
 
1716
                'update_post_term_cache' => false,
 
1717
                'update_post_meta_cache' => false
 
1718
        );
 
1719
 
 
1720
        $term_array = array();
 
1721
 
 
1722
        if ( ! is_array( $excluded_terms ) ) {
 
1723
                if ( ! empty( $excluded_terms ) )
 
1724
                        $excluded_terms = explode( ',', $excluded_terms );
 
1725
                else
 
1726
                        $excluded_terms = array();
 
1727
        }
 
1728
 
 
1729
        if ( $in_same_term || ! empty( $excluded_terms ) ) {
 
1730
                if ( $in_same_term )
 
1731
                        $term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );
 
1732
 
 
1733
                if ( ! empty( $excluded_terms ) ) {
 
1734
                        $excluded_terms = array_map( 'intval', $excluded_terms );
 
1735
                        $excluded_terms = array_diff( $excluded_terms, $term_array );
 
1736
 
 
1737
                        $inverse_terms = array();
 
1738
                        foreach ( $excluded_terms as $excluded_term )
 
1739
                                $inverse_terms[] = $excluded_term * -1;
 
1740
                        $excluded_terms = $inverse_terms;
 
1741
                }
 
1742
 
 
1743
                $query_args[ 'tax_query' ] = array( array(
 
1744
                        'taxonomy' => $taxonomy,
 
1745
                        'terms' => array_merge( $term_array, $excluded_terms )
 
1746
                ) );
 
1747
        }
 
1748
 
 
1749
        return get_posts( $query_args );
 
1750
}
 
1751
 
 
1752
/*
 
1753
 * Get previous post link that is adjacent to the current post.
 
1754
 *
 
1755
 * @since 3.7.0
 
1756
 *
 
1757
 * @param string       $format         Optional. Link anchor format.
 
1758
 * @param string       $link           Optional. Link permalink format.
 
1759
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1760
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1761
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1762
 * @return string
 
1763
 */
 
1764
function get_previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1765
        return get_adjacent_post_link( $format, $link, $in_same_term, $excluded_terms, true, $taxonomy );
 
1766
}
 
1767
 
 
1768
/**
 
1769
 * Display previous post link that is adjacent to the current post.
 
1770
 *
 
1771
 * @since 1.5.0
 
1772
 * @see get_previous_post_link()
 
1773
 *
 
1774
 * @param string       $format         Optional. Link anchor format.
 
1775
 * @param string       $link           Optional. Link permalink format.
 
1776
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1777
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1778
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1779
 */
 
1780
function previous_post_link( $format = '&laquo; %link', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1781
        echo get_previous_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy );
 
1782
}
 
1783
 
 
1784
/**
 
1785
 * Get next post link that is adjacent to the current post.
 
1786
 *
 
1787
 * @since 3.7.0
 
1788
 *
 
1789
 * @param string       $format         Optional. Link anchor format.
 
1790
 * @param string       $link           Optional. Link permalink format.
 
1791
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1792
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1793
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1794
 * @return string
 
1795
 */
 
1796
function get_next_post_link( $format = '%link &raquo;', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1797
        return get_adjacent_post_link( $format, $link, $in_same_term, $excluded_terms, false, $taxonomy );
 
1798
}
 
1799
 
 
1800
/**
 
1801
 * Display next post link that is adjacent to the current post.
 
1802
 *
 
1803
 * @since 1.5.0
 
1804
 * @see get_next_post_link()
 
1805
 *
 
1806
 * @param string       $format         Optional. Link anchor format.
 
1807
 * @param string       $link           Optional. Link permalink format.
 
1808
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1809
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs.
 
1810
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1811
 */
 
1812
function next_post_link( $format = '%link &raquo;', $link = '%title', $in_same_term = false, $excluded_terms = '', $taxonomy = 'category' ) {
 
1813
         echo get_next_post_link( $format, $link, $in_same_term, $excluded_terms, $taxonomy );
 
1814
}
 
1815
 
 
1816
/**
 
1817
 * Get adjacent post link.
 
1818
 *
 
1819
 * Can be either next post link or previous.
 
1820
 *
 
1821
 * @since 3.7.0
 
1822
 *
 
1823
 * @param string       $format         Link anchor format.
 
1824
 * @param string       $link           Link permalink format.
 
1825
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1826
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded terms IDs.
 
1827
 * @param bool         $previous       Optional. Whether to display link to previous or next post. Default true.
 
1828
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1829
 * @return string
 
1830
 */
 
1831
function get_adjacent_post_link( $format, $link, $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
 
1832
        if ( $previous && is_attachment() )
 
1833
                $post = get_post( get_post()->post_parent );
 
1834
        else
 
1835
                $post = get_adjacent_post( $in_same_term, $excluded_terms, $previous, $taxonomy );
 
1836
 
 
1837
        if ( ! $post ) {
 
1838
                $output = '';
 
1839
        } else {
 
1840
                $title = $post->post_title;
 
1841
 
 
1842
                if ( empty( $post->post_title ) )
 
1843
                        $title = $previous ? __( 'Previous Post' ) : __( 'Next Post' );
 
1844
 
 
1845
                /** This filter is documented in wp-includes/post-template.php */
 
1846
                $title = apply_filters( 'the_title', $title, $post->ID );
 
1847
 
 
1848
                $date = mysql2date( get_option( 'date_format' ), $post->post_date );
 
1849
                $rel = $previous ? 'prev' : 'next';
 
1850
 
 
1851
                $string = '<a href="' . get_permalink( $post ) . '" rel="'.$rel.'">';
 
1852
                $inlink = str_replace( '%title', $title, $link );
 
1853
                $inlink = str_replace( '%date', $date, $inlink );
 
1854
                $inlink = $string . $inlink . '</a>';
 
1855
 
 
1856
                $output = str_replace( '%link', $inlink, $format );
 
1857
        }
 
1858
 
 
1859
        $adjacent = $previous ? 'previous' : 'next';
 
1860
 
 
1861
        /**
 
1862
         * Filter the adjacent post link.
 
1863
         *
 
1864
         * The dynamic portion of the hook name, $adjacent, refers to the type
 
1865
         * of adjacency, 'next' or 'previous'.
 
1866
         *
 
1867
         * @since 2.6.0
 
1868
         *
 
1869
         * @param string  $output The adjacent post link.
 
1870
         * @param string  $format Link anchor format.
 
1871
         * @param string  $link   Link permalink format.
 
1872
         * @param WP_Post $post   The adjacent post.
 
1873
         */
 
1874
        return apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post );
 
1875
}
 
1876
 
 
1877
/**
 
1878
 * Display adjacent post link.
 
1879
 *
 
1880
 * Can be either next post link or previous.
 
1881
 *
 
1882
 * @since 2.5.0
 
1883
 * @uses get_adjacent_post_link()
 
1884
 *
 
1885
 * @param string       $format         Link anchor format.
 
1886
 * @param string       $link           Link permalink format.
 
1887
 * @param bool         $in_same_term   Optional. Whether link should be in a same taxonomy term.
 
1888
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded category IDs.
 
1889
 * @param bool         $previous       Optional. Whether to display link to previous or next post. Default true.
 
1890
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 
1891
 * @return string
 
1892
 */
 
1893
function adjacent_post_link( $format, $link, $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
 
1894
        echo get_adjacent_post_link( $format, $link, $in_same_term, $excluded_terms, $previous, $taxonomy );
 
1895
}
 
1896
 
 
1897
/**
 
1898
 * Retrieve links for page numbers.
 
1899
 *
 
1900
 * @since 1.5.0
 
1901
 *
 
1902
 * @param int $pagenum Optional. Page ID.
 
1903
 * @param bool $escape Optional. Whether to escape the URL for display, with esc_url(). Defaults to true.
 
1904
*       Otherwise, prepares the URL with esc_url_raw().
 
1905
 * @return string
 
1906
 */
 
1907
function get_pagenum_link($pagenum = 1, $escape = true ) {
 
1908
        global $wp_rewrite;
 
1909
 
 
1910
        $pagenum = (int) $pagenum;
 
1911
 
 
1912
        $request = remove_query_arg( 'paged' );
 
1913
 
 
1914
        $home_root = parse_url(home_url());
 
1915
        $home_root = ( isset($home_root['path']) ) ? $home_root['path'] : '';
 
1916
        $home_root = preg_quote( $home_root, '|' );
 
1917
 
 
1918
        $request = preg_replace('|^'. $home_root . '|i', '', $request);
 
1919
        $request = preg_replace('|^/+|', '', $request);
 
1920
 
 
1921
        if ( !$wp_rewrite->using_permalinks() || is_admin() ) {
 
1922
                $base = trailingslashit( get_bloginfo( 'url' ) );
 
1923
 
 
1924
                if ( $pagenum > 1 ) {
 
1925
                        $result = add_query_arg( 'paged', $pagenum, $base . $request );
 
1926
                } else {
 
1927
                        $result = $base . $request;
 
1928
                }
 
1929
        } else {
 
1930
                $qs_regex = '|\?.*?$|';
 
1931
                preg_match( $qs_regex, $request, $qs_match );
 
1932
 
 
1933
                if ( !empty( $qs_match[0] ) ) {
 
1934
                        $query_string = $qs_match[0];
 
1935
                        $request = preg_replace( $qs_regex, '', $request );
 
1936
                } else {
 
1937
                        $query_string = '';
 
1938
                }
 
1939
 
 
1940
                $request = preg_replace( "|$wp_rewrite->pagination_base/\d+/?$|", '', $request);
 
1941
                $request = preg_replace( '|^' . preg_quote( $wp_rewrite->index, '|' ) . '|i', '', $request);
 
1942
                $request = ltrim($request, '/');
 
1943
 
 
1944
                $base = trailingslashit( get_bloginfo( 'url' ) );
 
1945
 
 
1946
                if ( $wp_rewrite->using_index_permalinks() && ( $pagenum > 1 || '' != $request ) )
 
1947
                        $base .= $wp_rewrite->index . '/';
 
1948
 
 
1949
                if ( $pagenum > 1 ) {
 
1950
                        $request = ( ( !empty( $request ) ) ? trailingslashit( $request ) : $request ) . user_trailingslashit( $wp_rewrite->pagination_base . "/" . $pagenum, 'paged' );
 
1951
                }
 
1952
 
 
1953
                $result = $base . $request . $query_string;
 
1954
        }
 
1955
 
 
1956
        /**
 
1957
         * Filter the page number link for the current request.
 
1958
         *
 
1959
         * @since 2.5.0
 
1960
         *
 
1961
         * @param string $result The page number link.
 
1962
         */
 
1963
        $result = apply_filters( 'get_pagenum_link', $result );
 
1964
 
 
1965
        if ( $escape )
 
1966
                return esc_url( $result );
 
1967
        else
 
1968
                return esc_url_raw( $result );
 
1969
}
 
1970
 
 
1971
/**
 
1972
 * Retrieve next posts page link.
 
1973
 *
 
1974
 * Backported from 2.1.3 to 2.0.10.
 
1975
 *
 
1976
 * @since 2.0.10
 
1977
 *
 
1978
 * @param int $max_page Optional. Max pages.
 
1979
 * @return string
 
1980
 */
 
1981
function get_next_posts_page_link($max_page = 0) {
 
1982
        global $paged;
 
1983
 
 
1984
        if ( !is_single() ) {
 
1985
                if ( !$paged )
 
1986
                        $paged = 1;
 
1987
                $nextpage = intval($paged) + 1;
 
1988
                if ( !$max_page || $max_page >= $nextpage )
 
1989
                        return get_pagenum_link($nextpage);
 
1990
        }
 
1991
}
 
1992
 
 
1993
/**
 
1994
 * Display or return the next posts page link.
 
1995
 *
 
1996
 * @since 0.71
 
1997
 *
 
1998
 * @param int $max_page Optional. Max pages.
 
1999
 * @param boolean $echo Optional. Echo or return;
 
2000
 */
 
2001
function next_posts( $max_page = 0, $echo = true ) {
 
2002
        $output = esc_url( get_next_posts_page_link( $max_page ) );
 
2003
 
 
2004
        if ( $echo )
 
2005
                echo $output;
 
2006
        else
 
2007
                return $output;
 
2008
}
 
2009
 
 
2010
/**
 
2011
 * Return the next posts page link.
 
2012
 *
 
2013
 * @since 2.7.0
 
2014
 *
 
2015
 * @param string $label Content for link text.
 
2016
 * @param int $max_page Optional. Max pages.
 
2017
 * @return string|null
 
2018
 */
 
2019
function get_next_posts_link( $label = null, $max_page = 0 ) {
 
2020
        global $paged, $wp_query;
 
2021
 
 
2022
        if ( !$max_page )
 
2023
                $max_page = $wp_query->max_num_pages;
 
2024
 
 
2025
        if ( !$paged )
 
2026
                $paged = 1;
 
2027
 
 
2028
        $nextpage = intval($paged) + 1;
 
2029
 
 
2030
        if ( null === $label )
 
2031
                $label = __( 'Next Page &raquo;' );
 
2032
 
 
2033
        if ( !is_single() && ( $nextpage <= $max_page ) ) {
 
2034
                /**
 
2035
                 * Filter the anchor tag attributes for the next posts page link.
 
2036
                 *
 
2037
                 * @since 2.7.0
 
2038
                 *
 
2039
                 * @param string $attributes Attributes for the anchor tag.
 
2040
                 */
 
2041
                $attr = apply_filters( 'next_posts_link_attributes', '' );
 
2042
 
 
2043
                return '<a href="' . next_posts( $max_page, false ) . "\" $attr>" . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) . '</a>';
 
2044
        }
 
2045
}
 
2046
 
 
2047
/**
 
2048
 * Display the next posts page link.
 
2049
 *
 
2050
 * @since 0.71
 
2051
 * @uses get_next_posts_link()
 
2052
 *
 
2053
 * @param string $label Content for link text.
 
2054
 * @param int $max_page Optional. Max pages.
 
2055
 */
 
2056
function next_posts_link( $label = null, $max_page = 0 ) {
 
2057
        echo get_next_posts_link( $label, $max_page );
 
2058
}
 
2059
 
 
2060
/**
 
2061
 * Retrieve previous posts page link.
 
2062
 *
 
2063
 * Will only return string, if not on a single page or post.
 
2064
 *
 
2065
 * Backported to 2.0.10 from 2.1.3.
 
2066
 *
 
2067
 * @since 2.0.10
 
2068
 *
 
2069
 * @return string|null
 
2070
 */
 
2071
function get_previous_posts_page_link() {
 
2072
        global $paged;
 
2073
 
 
2074
        if ( !is_single() ) {
 
2075
                $nextpage = intval($paged) - 1;
 
2076
                if ( $nextpage < 1 )
 
2077
                        $nextpage = 1;
 
2078
                return get_pagenum_link($nextpage);
 
2079
        }
 
2080
}
 
2081
 
 
2082
/**
 
2083
 * Display or return the previous posts page link.
 
2084
 *
 
2085
 * @since 0.71
 
2086
 *
 
2087
 * @param boolean $echo Optional. Echo or return;
 
2088
 */
 
2089
function previous_posts( $echo = true ) {
 
2090
        $output = esc_url( get_previous_posts_page_link() );
 
2091
 
 
2092
        if ( $echo )
 
2093
                echo $output;
 
2094
        else
 
2095
                return $output;
 
2096
}
 
2097
 
 
2098
/**
 
2099
 * Return the previous posts page link.
 
2100
 *
 
2101
 * @since 2.7.0
 
2102
 *
 
2103
 * @param string $label Optional. Previous page link text.
 
2104
 * @return string|null
 
2105
 */
 
2106
function get_previous_posts_link( $label = null ) {
 
2107
        global $paged;
 
2108
 
 
2109
        if ( null === $label )
 
2110
                $label = __( '&laquo; Previous Page' );
 
2111
 
 
2112
        if ( !is_single() && $paged > 1 ) {
 
2113
                /**
 
2114
                 * Filter the anchor tag attributes for the previous posts page link.
 
2115
                 *
 
2116
                 * @since 2.7.0
 
2117
                 *
 
2118
                 * @param string $attributes Attributes for the anchor tag.
 
2119
                 */
 
2120
                $attr = apply_filters( 'previous_posts_link_attributes', '' );
 
2121
                return '<a href="' . previous_posts( false ) . "\" $attr>". preg_replace( '/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label ) .'</a>';
 
2122
        }
 
2123
}
 
2124
 
 
2125
/**
 
2126
 * Display the previous posts page link.
 
2127
 *
 
2128
 * @since 0.71
 
2129
 * @uses get_previous_posts_link()
 
2130
 *
 
2131
 * @param string $label Optional. Previous page link text.
 
2132
 */
 
2133
function previous_posts_link( $label = null ) {
 
2134
        echo get_previous_posts_link( $label );
 
2135
}
 
2136
 
 
2137
/**
 
2138
 * Return post pages link navigation for previous and next pages.
 
2139
 *
 
2140
 * @since 2.8.0
 
2141
 *
 
2142
 * @param string|array $args Optional args.
 
2143
 * @return string The posts link navigation.
 
2144
 */
 
2145
function get_posts_nav_link( $args = array() ) {
 
2146
        global $wp_query;
 
2147
 
 
2148
        $return = '';
 
2149
 
 
2150
        if ( !is_singular() ) {
 
2151
                $defaults = array(
 
2152
                        'sep' => ' &#8212; ',
 
2153
                        'prelabel' => __('&laquo; Previous Page'),
 
2154
                        'nxtlabel' => __('Next Page &raquo;'),
 
2155
                );
 
2156
                $args = wp_parse_args( $args, $defaults );
 
2157
 
 
2158
                $max_num_pages = $wp_query->max_num_pages;
 
2159
                $paged = get_query_var('paged');
 
2160
 
 
2161
                //only have sep if there's both prev and next results
 
2162
                if ($paged < 2 || $paged >= $max_num_pages) {
 
2163
                        $args['sep'] = '';
 
2164
                }
 
2165
 
 
2166
                if ( $max_num_pages > 1 ) {
 
2167
                        $return = get_previous_posts_link($args['prelabel']);
 
2168
                        $return .= preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $args['sep']);
 
2169
                        $return .= get_next_posts_link($args['nxtlabel']);
 
2170
                }
 
2171
        }
 
2172
        return $return;
 
2173
 
 
2174
}
 
2175
 
 
2176
/**
 
2177
 * Display post pages link navigation for previous and next pages.
 
2178
 *
 
2179
 * @since 0.71
 
2180
 *
 
2181
 * @param string $sep Optional. Separator for posts navigation links.
 
2182
 * @param string $prelabel Optional. Label for previous pages.
 
2183
 * @param string $nxtlabel Optional Label for next pages.
 
2184
 */
 
2185
function posts_nav_link( $sep = '', $prelabel = '', $nxtlabel = '' ) {
 
2186
        $args = array_filter( compact('sep', 'prelabel', 'nxtlabel') );
 
2187
        echo get_posts_nav_link($args);
 
2188
}
 
2189
 
 
2190
/**
 
2191
 * Retrieve comments page number link.
 
2192
 *
 
2193
 * @since 2.7.0
 
2194
 *
 
2195
 * @param int $pagenum Optional. Page number.
 
2196
 * @return string
 
2197
 */
 
2198
function get_comments_pagenum_link( $pagenum = 1, $max_page = 0 ) {
 
2199
        global $wp_rewrite;
 
2200
 
 
2201
        $pagenum = (int) $pagenum;
 
2202
 
 
2203
        $result = get_permalink();
 
2204
 
 
2205
        if ( 'newest' == get_option('default_comments_page') ) {
 
2206
                if ( $pagenum != $max_page ) {
 
2207
                        if ( $wp_rewrite->using_permalinks() )
 
2208
                                $result = user_trailingslashit( trailingslashit($result) . 'comment-page-' . $pagenum, 'commentpaged');
 
2209
                        else
 
2210
                                $result = add_query_arg( 'cpage', $pagenum, $result );
 
2211
                }
 
2212
        } elseif ( $pagenum > 1 ) {
 
2213
                if ( $wp_rewrite->using_permalinks() )
 
2214
                        $result = user_trailingslashit( trailingslashit($result) . 'comment-page-' . $pagenum, 'commentpaged');
 
2215
                else
 
2216
                        $result = add_query_arg( 'cpage', $pagenum, $result );
 
2217
        }
 
2218
 
 
2219
        $result .= '#comments';
 
2220
 
 
2221
        /**
 
2222
         * Filter the comments page number link for the current request.
 
2223
         *
 
2224
         * @since 2.7.0
 
2225
         *
 
2226
         * @param string $result The comments page number link.
 
2227
         */
 
2228
        $result = apply_filters( 'get_comments_pagenum_link', $result );
 
2229
 
 
2230
        return $result;
 
2231
}
 
2232
 
 
2233
/**
 
2234
 * Return the link to next comments page.
 
2235
 *
 
2236
 * @since 2.7.1
 
2237
 *
 
2238
 * @param string $label Optional. Label for link text.
 
2239
 * @param int $max_page Optional. Max page.
 
2240
 * @return string|null
 
2241
 */
 
2242
function get_next_comments_link( $label = '', $max_page = 0 ) {
 
2243
        global $wp_query;
 
2244
 
 
2245
        if ( !is_singular() || !get_option('page_comments') )
 
2246
                return;
 
2247
 
 
2248
        $page = get_query_var('cpage');
 
2249
 
 
2250
        $nextpage = intval($page) + 1;
 
2251
 
 
2252
        if ( empty($max_page) )
 
2253
                $max_page = $wp_query->max_num_comment_pages;
 
2254
 
 
2255
        if ( empty($max_page) )
 
2256
                $max_page = get_comment_pages_count();
 
2257
 
 
2258
        if ( $nextpage > $max_page )
 
2259
                return;
 
2260
 
 
2261
        if ( empty($label) )
 
2262
                $label = __('Newer Comments &raquo;');
 
2263
 
 
2264
        /**
 
2265
         * Filter the anchor tag attributes for the next comments page link.
 
2266
         *
 
2267
         * @since 2.7.0
 
2268
         *
 
2269
         * @param string $attributes Attributes for the anchor tag.
 
2270
         */
 
2271
        return '<a href="' . esc_url( get_comments_pagenum_link( $nextpage, $max_page ) ) . '" ' . apply_filters( 'next_comments_link_attributes', '' ) . '>'. preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) .'</a>';
 
2272
}
 
2273
 
 
2274
/**
 
2275
 * Display the link to next comments page.
 
2276
 *
 
2277
 * @since 2.7.0
 
2278
 *
 
2279
 * @param string $label Optional. Label for link text.
 
2280
 * @param int $max_page Optional. Max page.
 
2281
 */
 
2282
function next_comments_link( $label = '', $max_page = 0 ) {
 
2283
        echo get_next_comments_link( $label, $max_page );
 
2284
}
 
2285
 
 
2286
/**
 
2287
 * Return the previous comments page link.
 
2288
 *
 
2289
 * @since 2.7.1
 
2290
 *
 
2291
 * @param string $label Optional. Label for comments link text.
 
2292
 * @return string|null
 
2293
 */
 
2294
function get_previous_comments_link( $label = '' ) {
 
2295
        if ( !is_singular() || !get_option('page_comments') )
 
2296
                return;
 
2297
 
 
2298
        $page = get_query_var('cpage');
 
2299
 
 
2300
        if ( intval($page) <= 1 )
 
2301
                return;
 
2302
 
 
2303
        $prevpage = intval($page) - 1;
 
2304
 
 
2305
        if ( empty($label) )
 
2306
                $label = __('&laquo; Older Comments');
 
2307
 
 
2308
        /**
 
2309
         * Filter the anchor tag attributes for the previous comments page link.
 
2310
         *
 
2311
         * @since 2.7.0
 
2312
         *
 
2313
         * @param string $attributes Attributes for the anchor tag.
 
2314
         */
 
2315
        return '<a href="' . esc_url( get_comments_pagenum_link( $prevpage ) ) . '" ' . apply_filters( 'previous_comments_link_attributes', '' ) . '>' . preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $label) .'</a>';
 
2316
}
 
2317
 
 
2318
/**
 
2319
 * Display the previous comments page link.
 
2320
 *
 
2321
 * @since 2.7.0
 
2322
 *
 
2323
 * @param string $label Optional. Label for comments link text.
 
2324
 */
 
2325
function previous_comments_link( $label = '' ) {
 
2326
        echo get_previous_comments_link( $label );
 
2327
}
 
2328
 
 
2329
/**
 
2330
 * Create pagination links for the comments on the current post.
 
2331
 *
 
2332
 * @see paginate_links()
 
2333
 * @since 2.7.0
 
2334
 *
 
2335
 * @param string|array $args Optional args. See paginate_links().
 
2336
 * @return string Markup for pagination links.
 
2337
*/
 
2338
function paginate_comments_links($args = array()) {
 
2339
        global $wp_rewrite;
 
2340
 
 
2341
        if ( !is_singular() || !get_option('page_comments') )
 
2342
                return;
 
2343
 
 
2344
        $page = get_query_var('cpage');
 
2345
        if ( !$page )
 
2346
                $page = 1;
 
2347
        $max_page = get_comment_pages_count();
 
2348
        $defaults = array(
 
2349
                'base' => add_query_arg( 'cpage', '%#%' ),
 
2350
                'format' => '',
 
2351
                'total' => $max_page,
 
2352
                'current' => $page,
 
2353
                'echo' => true,
 
2354
                'add_fragment' => '#comments'
 
2355
        );
 
2356
        if ( $wp_rewrite->using_permalinks() )
 
2357
                $defaults['base'] = user_trailingslashit(trailingslashit(get_permalink()) . 'comment-page-%#%', 'commentpaged');
 
2358
 
 
2359
        $args = wp_parse_args( $args, $defaults );
 
2360
        $page_links = paginate_links( $args );
 
2361
 
 
2362
        if ( $args['echo'] )
 
2363
                echo $page_links;
 
2364
        else
 
2365
                return $page_links;
 
2366
}
 
2367
 
 
2368
/**
 
2369
 * Retrieve the Press This bookmarklet link.
 
2370
 *
 
2371
 * Use this in 'a' element 'href' attribute.
 
2372
 *
 
2373
 * @since 2.6.0
 
2374
 *
 
2375
 * @return string
 
2376
 */
 
2377
function get_shortcut_link() {
 
2378
        // In case of breaking changes, version this. #WP20071
 
2379
        $link = "javascript:
 
2380
                        var d=document,
 
2381
                        w=window,
 
2382
                        e=w.getSelection,
 
2383
                        k=d.getSelection,
 
2384
                        x=d.selection,
 
2385
                        s=(e?e():(k)?k():(x?x.createRange().text:0)),
 
2386
                        f='" . admin_url('press-this.php') . "',
 
2387
                        l=d.location,
 
2388
                        e=encodeURIComponent,
 
2389
                        u=f+'?u='+e(l.href)+'&t='+e(d.title)+'&s='+e(s)+'&v=4';
 
2390
                        a=function(){if(!w.open(u,'t','toolbar=0,resizable=1,scrollbars=1,status=1,width=720,height=570'))l.href=u;};
 
2391
                        if (/Firefox/.test(navigator.userAgent)) setTimeout(a, 0); else a();
 
2392
                        void(0)";
 
2393
 
 
2394
        $link = str_replace(array("\r", "\n", "\t"),  '', $link);
 
2395
 
 
2396
        /**
 
2397
         * Filter the Press This bookmarklet link.
 
2398
         *
 
2399
         * @since 2.6.0
 
2400
         *
 
2401
         * @param string $link The Press This bookmarklet link.
 
2402
         */
 
2403
        return apply_filters( 'shortcut_link', $link );
 
2404
}
 
2405
 
 
2406
/**
 
2407
 * Retrieve the home url for the current site.
 
2408
 *
 
2409
 * Returns the 'home' option with the appropriate protocol, 'https' if
 
2410
 * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
 
2411
 * overridden.
 
2412
 *
 
2413
 * @since 3.0.0
 
2414
 *
 
2415
 * @uses get_home_url()
 
2416
 *
 
2417
 * @param  string $path   (optional) Path relative to the home url.
 
2418
 * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
 
2419
 * @return string Home url link with optional path appended.
 
2420
*/
 
2421
function home_url( $path = '', $scheme = null ) {
 
2422
        return get_home_url( null, $path, $scheme );
 
2423
}
 
2424
 
 
2425
/**
 
2426
 * Retrieve the home url for a given site.
 
2427
 *
 
2428
 * Returns the 'home' option with the appropriate protocol, 'https' if
 
2429
 * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
 
2430
 * overridden.
 
2431
 *
 
2432
 * @since 3.0.0
 
2433
 *
 
2434
 * @param  int $blog_id   (optional) Blog ID. Defaults to current blog.
 
2435
 * @param  string $path   (optional) Path relative to the home url.
 
2436
 * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
 
2437
 * @return string Home url link with optional path appended.
 
2438
*/
 
2439
function get_home_url( $blog_id = null, $path = '', $scheme = null ) {
 
2440
        $orig_scheme = $scheme;
 
2441
 
 
2442
        if ( empty( $blog_id ) || !is_multisite() ) {
 
2443
                $url = get_option( 'home' );
 
2444
        } else {
 
2445
                switch_to_blog( $blog_id );
 
2446
                $url = get_option( 'home' );
 
2447
                restore_current_blog();
 
2448
        }
 
2449
 
 
2450
        if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) ) {
 
2451
                if ( is_ssl() && ! is_admin() && 'wp-login.php' !== $GLOBALS['pagenow'] )
 
2452
                        $scheme = 'https';
 
2453
                else
 
2454
                        $scheme = parse_url( $url, PHP_URL_SCHEME );
 
2455
        }
 
2456
 
 
2457
        $url = set_url_scheme( $url, $scheme );
 
2458
 
 
2459
        if ( $path && is_string( $path ) )
 
2460
                $url .= '/' . ltrim( $path, '/' );
 
2461
 
 
2462
        /**
 
2463
         * Filter the home URL.
 
2464
         *
 
2465
         * @since 3.0.0
 
2466
         *
 
2467
         * @param string      $url         The complete home URL including scheme and path.
 
2468
         * @param string      $path        Path relative to the home URL. Blank string if no path is specified.
 
2469
         * @param string|null $orig_scheme Scheme to give the home URL context. Accepts 'http', 'https', 'relative' or null.
 
2470
         * @param int|null    $blog_id     Blog ID, or null for the current blog.
 
2471
         */
 
2472
        return apply_filters( 'home_url', $url, $path, $orig_scheme, $blog_id );
 
2473
}
 
2474
 
 
2475
/**
 
2476
 * Retrieve the site url for the current site.
 
2477
 *
 
2478
 * Returns the 'site_url' option with the appropriate protocol, 'https' if
 
2479
 * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
 
2480
 * overridden.
 
2481
 *
 
2482
 * @since 3.0.0
 
2483
 *
 
2484
 * @uses get_site_url()
 
2485
 *
 
2486
 * @param string $path Optional. Path relative to the site url.
 
2487
 * @param string $scheme Optional. Scheme to give the site url context. See set_url_scheme().
 
2488
 * @return string Site url link with optional path appended.
 
2489
*/
 
2490
function site_url( $path = '', $scheme = null ) {
 
2491
        return get_site_url( null, $path, $scheme );
 
2492
}
 
2493
 
 
2494
/**
 
2495
 * Retrieve the site url for a given site.
 
2496
 *
 
2497
 * Returns the 'site_url' option with the appropriate protocol, 'https' if
 
2498
 * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
 
2499
 * overridden.
 
2500
 *
 
2501
 * @since 3.0.0
 
2502
 *
 
2503
 * @param int $blog_id (optional) Blog ID. Defaults to current blog.
 
2504
 * @param string $path Optional. Path relative to the site url.
 
2505
 * @param string $scheme Optional. Scheme to give the site url context. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
 
2506
 * @return string Site url link with optional path appended.
 
2507
*/
 
2508
function get_site_url( $blog_id = null, $path = '', $scheme = null ) {
 
2509
        if ( empty( $blog_id ) || !is_multisite() ) {
 
2510
                $url = get_option( 'siteurl' );
 
2511
        } else {
 
2512
                switch_to_blog( $blog_id );
 
2513
                $url = get_option( 'siteurl' );
 
2514
                restore_current_blog();
 
2515
        }
 
2516
 
 
2517
        $url = set_url_scheme( $url, $scheme );
 
2518
 
 
2519
        if ( $path && is_string( $path ) )
 
2520
                $url .= '/' . ltrim( $path, '/' );
 
2521
 
 
2522
        /**
 
2523
         * Filter the site URL.
 
2524
         *
 
2525
         * @since 2.7.0
 
2526
         *
 
2527
         * @param string      $url     The complete site URL including scheme and path.
 
2528
         * @param string      $path    Path relative to the site URL. Blank string if no path is specified.
 
2529
         * @param string|null $scheme  Scheme to give the site URL context. Accepts 'http', 'https', 'login',
 
2530
         *                             'login_post', 'admin', 'relative' or null.
 
2531
         * @param int|null    $blog_id Blog ID, or null for the current blog.
 
2532
         */
 
2533
        return apply_filters( 'site_url', $url, $path, $scheme, $blog_id );
 
2534
}
 
2535
 
 
2536
/**
 
2537
 * Retrieve the url to the admin area for the current site.
 
2538
 *
 
2539
 * @since 2.6.0
 
2540
 *
 
2541
 * @param string $path Optional path relative to the admin url.
 
2542
 * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
 
2543
 * @return string Admin url link with optional path appended.
 
2544
*/
 
2545
function admin_url( $path = '', $scheme = 'admin' ) {
 
2546
        return get_admin_url( null, $path, $scheme );
 
2547
}
 
2548
 
 
2549
/**
 
2550
 * Retrieve the url to the admin area for a given site.
 
2551
 *
 
2552
 * @since 3.0.0
 
2553
 *
 
2554
 * @param int $blog_id (optional) Blog ID. Defaults to current blog.
 
2555
 * @param string $path Optional path relative to the admin url.
 
2556
 * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
 
2557
 * @return string Admin url link with optional path appended.
 
2558
*/
 
2559
function get_admin_url( $blog_id = null, $path = '', $scheme = 'admin' ) {
 
2560
        $url = get_site_url($blog_id, 'wp-admin/', $scheme);
 
2561
 
 
2562
        if ( $path && is_string( $path ) )
 
2563
                $url .= ltrim( $path, '/' );
 
2564
 
 
2565
        /**
 
2566
         * Filter the admin area URL.
 
2567
         *
 
2568
         * @since 2.8.0
 
2569
         *
 
2570
         * @param string   $url     The complete admin area URL including scheme and path.
 
2571
         * @param string   $path    Path relative to the admin area URL. Blank string if no path is specified.
 
2572
         * @param int|null $blog_id Blog ID, or null for the current blog.
 
2573
         */
 
2574
        return apply_filters( 'admin_url', $url, $path, $blog_id );
 
2575
}
 
2576
 
 
2577
/**
 
2578
 * Retrieve the url to the includes directory.
 
2579
 *
 
2580
 * @since 2.6.0
 
2581
 *
 
2582
 * @param string $path Optional. Path relative to the includes url.
 
2583
 * @param string $scheme Optional. Scheme to give the includes url context.
 
2584
 * @return string Includes url link with optional path appended.
 
2585
*/
 
2586
function includes_url( $path = '', $scheme = null ) {
 
2587
        $url = site_url( '/' . WPINC . '/', $scheme );
 
2588
 
 
2589
        if ( $path && is_string( $path ) )
 
2590
                $url .= ltrim($path, '/');
 
2591
 
 
2592
        /**
 
2593
         * Filter the URL to the includes directory.
 
2594
         *
 
2595
         * @since 2.8.0
 
2596
         *
 
2597
         * @param string $url  The complete URL to the includes directory including scheme and path.
 
2598
         * @param string $path Path relative to the URL to the wp-includes directory. Blank string
 
2599
         *                     if no path is specified.
 
2600
         */
 
2601
        return apply_filters( 'includes_url', $url, $path );
 
2602
}
 
2603
 
 
2604
/**
 
2605
 * Retrieve the url to the content directory.
 
2606
 *
 
2607
 * @since 2.6.0
 
2608
 *
 
2609
 * @param string $path Optional. Path relative to the content url.
 
2610
 * @return string Content url link with optional path appended.
 
2611
*/
 
2612
function content_url($path = '') {
 
2613
        $url = set_url_scheme( WP_CONTENT_URL );
 
2614
 
 
2615
        if ( $path && is_string( $path ) )
 
2616
                $url .= '/' . ltrim($path, '/');
 
2617
 
 
2618
        /**
 
2619
         * Filter the URL to the content directory.
 
2620
         *
 
2621
         * @since 2.8.0
 
2622
         *
 
2623
         * @param string $url  The complete URL to the content directory including scheme and path.
 
2624
         * @param string $path Path relative to the URL to the content directory. Blank string
 
2625
         *                     if no path is specified.
 
2626
         */
 
2627
        return apply_filters( 'content_url', $url, $path);
 
2628
}
 
2629
 
 
2630
/**
 
2631
 * Retrieve a URL within the plugins or mu-plugins directory.
 
2632
 *
 
2633
 * Defaults to the plugins directory URL if no arguments are supplied.
 
2634
 *
 
2635
 * @since 2.6.0
 
2636
 *
 
2637
 * @param  string $path   Optional. Extra path appended to the end of the URL, including
 
2638
 *                        the relative directory if $plugin is supplied. Default empty.
 
2639
 * @param  string $plugin Optional. A full path to a file inside a plugin or mu-plugin.
 
2640
 *                        The URL will be relative to its directory. Default empty.
 
2641
 *                        Typically this is done by passing `__FILE__` as the argument.
 
2642
 * @return string Plugins URL link with optional paths appended.
 
2643
*/
 
2644
function plugins_url( $path = '', $plugin = '' ) {
 
2645
 
 
2646
        $path = wp_normalize_path( $path );
 
2647
        $plugin = wp_normalize_path( $plugin );
 
2648
        $mu_plugin_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
 
2649
 
 
2650
        if ( !empty($plugin) && 0 === strpos($plugin, $mu_plugin_dir) )
 
2651
                $url = WPMU_PLUGIN_URL;
 
2652
        else
 
2653
                $url = WP_PLUGIN_URL;
 
2654
 
 
2655
 
 
2656
        $url = set_url_scheme( $url );
 
2657
 
 
2658
        if ( !empty($plugin) && is_string($plugin) ) {
 
2659
                $folder = dirname(plugin_basename($plugin));
 
2660
                if ( '.' != $folder )
 
2661
                        $url .= '/' . ltrim($folder, '/');
 
2662
        }
 
2663
 
 
2664
        if ( $path && is_string( $path ) )
 
2665
                $url .= '/' . ltrim($path, '/');
 
2666
 
 
2667
        /**
 
2668
         * Filter the URL to the plugins directory.
 
2669
         *
 
2670
         * @since 2.8.0
 
2671
         *
 
2672
         * @param string $url    The complete URL to the plugins directory including scheme and path.
 
2673
         * @param string $path   Path relative to the URL to the plugins directory. Blank string
 
2674
         *                       if no path is specified.
 
2675
         * @param string $plugin The plugin file path to be relative to. Blank string if no plugin
 
2676
         *                       is specified.
 
2677
         */
 
2678
        return apply_filters( 'plugins_url', $url, $path, $plugin );
 
2679
}
 
2680
 
 
2681
/**
 
2682
 * Retrieve the site url for the current network.
 
2683
 *
 
2684
 * Returns the site url with the appropriate protocol, 'https' if
 
2685
 * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
 
2686
 * overridden.
 
2687
 *
 
2688
 * @since 3.0.0
 
2689
 *
 
2690
 * @param string $path Optional. Path relative to the site url.
 
2691
 * @param string $scheme Optional. Scheme to give the site url context. See set_url_scheme().
 
2692
 * @return string Site url link with optional path appended.
 
2693
*/
 
2694
function network_site_url( $path = '', $scheme = null ) {
 
2695
        if ( ! is_multisite() )
 
2696
                return site_url($path, $scheme);
 
2697
 
 
2698
        $current_site = get_current_site();
 
2699
 
 
2700
        if ( 'relative' == $scheme )
 
2701
                $url = $current_site->path;
 
2702
        else
 
2703
                $url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
 
2704
 
 
2705
        if ( $path && is_string( $path ) )
 
2706
                $url .= ltrim( $path, '/' );
 
2707
 
 
2708
        /**
 
2709
         * Filter the network site URL.
 
2710
         *
 
2711
         * @since 3.0.0
 
2712
         *
 
2713
         * @param string      $url    The complete network site URL including scheme and path.
 
2714
         * @param string      $path   Path relative to the network site URL. Blank string if
 
2715
         *                            no path is specified.
 
2716
         * @param string|null $scheme Scheme to give the URL context. Accepts 'http', 'https',
 
2717
         *                            'relative' or null.
 
2718
         */
 
2719
        return apply_filters( 'network_site_url', $url, $path, $scheme );
 
2720
}
 
2721
 
 
2722
/**
 
2723
 * Retrieve the home url for the current network.
 
2724
 *
 
2725
 * Returns the home url with the appropriate protocol, 'https' if
 
2726
 * is_ssl() and 'http' otherwise. If $scheme is 'http' or 'https', is_ssl() is
 
2727
 * overridden.
 
2728
 *
 
2729
 * @since 3.0.0
 
2730
 *
 
2731
 * @param  string $path   (optional) Path relative to the home url.
 
2732
 * @param  string $scheme (optional) Scheme to give the home url context. Currently 'http', 'https', or 'relative'.
 
2733
 * @return string Home url link with optional path appended.
 
2734
*/
 
2735
function network_home_url( $path = '', $scheme = null ) {
 
2736
        if ( ! is_multisite() )
 
2737
                return home_url($path, $scheme);
 
2738
 
 
2739
        $current_site = get_current_site();
 
2740
        $orig_scheme = $scheme;
 
2741
 
 
2742
        if ( ! in_array( $scheme, array( 'http', 'https', 'relative' ) ) )
 
2743
                $scheme = is_ssl() && ! is_admin() ? 'https' : 'http';
 
2744
 
 
2745
        if ( 'relative' == $scheme )
 
2746
                $url = $current_site->path;
 
2747
        else
 
2748
                $url = set_url_scheme( 'http://' . $current_site->domain . $current_site->path, $scheme );
 
2749
 
 
2750
        if ( $path && is_string( $path ) )
 
2751
                $url .= ltrim( $path, '/' );
 
2752
 
 
2753
        /**
 
2754
         * Filter the network home URL.
 
2755
         *
 
2756
         * @since 3.0.0
 
2757
         *
 
2758
         * @param string      $url         The complete network home URL including scheme and path.
 
2759
         * @param string      $path        Path relative to the network home URL. Blank string
 
2760
         *                                 if no path is specified.
 
2761
         * @param string|null $orig_scheme Scheme to give the URL context. Accepts 'http', 'https',
 
2762
         *                                 'relative' or null.
 
2763
         */
 
2764
        return apply_filters( 'network_home_url', $url, $path, $orig_scheme);
 
2765
}
 
2766
 
 
2767
/**
 
2768
 * Retrieve the url to the admin area for the network.
 
2769
 *
 
2770
 * @since 3.0.0
 
2771
 *
 
2772
 * @param string $path Optional path relative to the admin url.
 
2773
 * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
 
2774
 * @return string Admin url link with optional path appended.
 
2775
*/
 
2776
function network_admin_url( $path = '', $scheme = 'admin' ) {
 
2777
        if ( ! is_multisite() )
 
2778
                return admin_url( $path, $scheme );
 
2779
 
 
2780
        $url = network_site_url('wp-admin/network/', $scheme);
 
2781
 
 
2782
        if ( $path && is_string( $path ) )
 
2783
                $url .= ltrim($path, '/');
 
2784
 
 
2785
        /**
 
2786
         * Filter the network admin URL.
 
2787
         *
 
2788
         * @since 3.0.0
 
2789
         *
 
2790
         * @param string $url  The complete network admin URL including scheme and path.
 
2791
         * @param string $path Path relative to the network admin URL. Blank string if
 
2792
         *                     no path is specified.
 
2793
         */
 
2794
        return apply_filters( 'network_admin_url', $url, $path );
 
2795
}
 
2796
 
 
2797
/**
 
2798
 * Retrieve the url to the admin area for the current user.
 
2799
 *
 
2800
 * @since 3.0.0
 
2801
 *
 
2802
 * @param string $path Optional path relative to the admin url.
 
2803
 * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
 
2804
 * @return string Admin url link with optional path appended.
 
2805
*/
 
2806
function user_admin_url( $path = '', $scheme = 'admin' ) {
 
2807
        $url = network_site_url('wp-admin/user/', $scheme);
 
2808
 
 
2809
        if ( $path && is_string( $path ) )
 
2810
                $url .= ltrim($path, '/');
 
2811
 
 
2812
        /**
 
2813
         * Filter the user admin URL for the current user.
 
2814
         *
 
2815
         * @since 3.1.0
 
2816
         *
 
2817
         * @param string $url  The complete URL including scheme and path.
 
2818
         * @param string $path Path relative to the URL. Blank string if
 
2819
         *                     no path is specified.
 
2820
         */
 
2821
        return apply_filters( 'user_admin_url', $url, $path );
 
2822
}
 
2823
 
 
2824
/**
 
2825
 * Retrieve the url to the admin area for either the current blog or the network depending on context.
 
2826
 *
 
2827
 * @since 3.1.0
 
2828
 *
 
2829
 * @param string $path Optional path relative to the admin url.
 
2830
 * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
 
2831
 * @return string Admin url link with optional path appended.
 
2832
*/
 
2833
function self_admin_url($path = '', $scheme = 'admin') {
 
2834
        if ( is_network_admin() )
 
2835
                return network_admin_url($path, $scheme);
 
2836
        elseif ( is_user_admin() )
 
2837
                return user_admin_url($path, $scheme);
 
2838
        else
 
2839
                return admin_url($path, $scheme);
 
2840
}
 
2841
 
 
2842
/**
 
2843
 * Set the scheme for a URL
 
2844
 *
 
2845
 * @since 3.4.0
 
2846
 *
 
2847
 * @param string $url Absolute url that includes a scheme
 
2848
 * @param string $scheme Optional. Scheme to give $url. Currently 'http', 'https', 'login', 'login_post', 'admin', or 'relative'.
 
2849
 * @return string $url URL with chosen scheme.
 
2850
 */
 
2851
function set_url_scheme( $url, $scheme = null ) {
 
2852
        $orig_scheme = $scheme;
 
2853
 
 
2854
        if ( ! $scheme ) {
 
2855
                $scheme = is_ssl() ? 'https' : 'http';
 
2856
        } elseif ( $scheme === 'admin' || $scheme === 'login' || $scheme === 'login_post' || $scheme === 'rpc' ) {
 
2857
                $scheme = is_ssl() || force_ssl_admin() ? 'https' : 'http';
 
2858
        } elseif ( $scheme !== 'http' && $scheme !== 'https' && $scheme !== 'relative' ) {
 
2859
                $scheme = is_ssl() ? 'https' : 'http';
 
2860
        }
 
2861
 
 
2862
        $url = trim( $url );
 
2863
        if ( substr( $url, 0, 2 ) === '//' )
 
2864
                $url = 'http:' . $url;
 
2865
 
 
2866
        if ( 'relative' == $scheme ) {
 
2867
                $url = ltrim( preg_replace( '#^\w+://[^/]*#', '', $url ) );
 
2868
                if ( $url !== '' && $url[0] === '/' )
 
2869
                        $url = '/' . ltrim($url , "/ \t\n\r\0\x0B" );
 
2870
        } else {
 
2871
                $url = preg_replace( '#^\w+://#', $scheme . '://', $url );
 
2872
        }
 
2873
 
 
2874
        /**
 
2875
         * Filter the resulting URL after setting the scheme.
 
2876
         *
 
2877
         * @since 3.4.0
 
2878
         *
 
2879
         * @param string $url         The complete URL including scheme and path.
 
2880
         * @param string $scheme      Scheme applied to the URL. One of 'http', 'https', or 'relative'.
 
2881
         * @param string $orig_scheme Scheme requested for the URL. One of 'http', 'https', 'login',
 
2882
         *                            'login_post', 'admin', 'rpc', or 'relative'.
 
2883
         */
 
2884
        return apply_filters( 'set_url_scheme', $url, $scheme, $orig_scheme );
 
2885
}
 
2886
 
 
2887
/**
 
2888
 * Get the URL to the user's dashboard.
 
2889
 *
 
2890
 * If a user does not belong to any site, the global user dashboard is used. If the user belongs to the current site,
 
2891
 * the dashboard for the current site is returned. If the user cannot edit the current site, the dashboard to the user's
 
2892
 * primary blog is returned.
 
2893
 *
 
2894
 * @since 3.1.0
 
2895
 *
 
2896
 * @param int $user_id Optional. User ID. Defaults to current user.
 
2897
 * @param string $path Optional path relative to the dashboard. Use only paths known to both blog and user admins.
 
2898
 * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes.
 
2899
 * @return string Dashboard url link with optional path appended.
 
2900
 */
 
2901
function get_dashboard_url( $user_id = 0, $path = '', $scheme = 'admin' ) {
 
2902
        $user_id = $user_id ? (int) $user_id : get_current_user_id();
 
2903
 
 
2904
        $blogs = get_blogs_of_user( $user_id );
 
2905
        if ( ! is_super_admin() && empty($blogs) ) {
 
2906
                $url = user_admin_url( $path, $scheme );
 
2907
        } elseif ( ! is_multisite() ) {
 
2908
                $url = admin_url( $path, $scheme );
 
2909
        } else {
 
2910
                $current_blog = get_current_blog_id();
 
2911
                if ( $current_blog  && ( is_super_admin( $user_id ) || in_array( $current_blog, array_keys( $blogs ) ) ) ) {
 
2912
                        $url = admin_url( $path, $scheme );
 
2913
                } else {
 
2914
                        $active = get_active_blog_for_user( $user_id );
 
2915
                        if ( $active )
 
2916
                                $url = get_admin_url( $active->blog_id, $path, $scheme );
 
2917
                        else
 
2918
                                $url = user_admin_url( $path, $scheme );
 
2919
                }
 
2920
        }
 
2921
 
 
2922
        /**
 
2923
         * Filter the dashboard URL for a user.
 
2924
         *
 
2925
         * @since 3.1.0
 
2926
         *
 
2927
         * @param string $url     The complete URL including scheme and path.
 
2928
         * @param int    $user_id The user ID.
 
2929
         * @param string $path    Path relative to the URL. Blank string if no path is specified.
 
2930
         * @param string $scheme  Scheme to give the URL context. Accepts 'http', 'https', 'login',
 
2931
         *                        'login_post', 'admin', 'relative' or null.
 
2932
         */
 
2933
        return apply_filters( 'user_dashboard_url', $url, $user_id, $path, $scheme);
 
2934
}
 
2935
 
 
2936
/**
 
2937
 * Get the URL to the user's profile editor.
 
2938
 *
 
2939
 * @since 3.1.0
 
2940
 *
 
2941
 * @param int    $user_id Optional. User ID. Defaults to current user.
 
2942
 * @param string $scheme  The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl().
 
2943
 *                        'http' or 'https' can be passed to force those schemes.
 
2944
 * @return string Dashboard url link with optional path appended.
 
2945
 */
 
2946
function get_edit_profile_url( $user_id = 0, $scheme = 'admin' ) {
 
2947
        $user_id = $user_id ? (int) $user_id : get_current_user_id();
 
2948
 
 
2949
        if ( is_user_admin() )
 
2950
                $url = user_admin_url( 'profile.php', $scheme );
 
2951
        elseif ( is_network_admin() )
 
2952
                $url = network_admin_url( 'profile.php', $scheme );
 
2953
        else
 
2954
                $url = get_dashboard_url( $user_id, 'profile.php', $scheme );
 
2955
 
 
2956
        /**
 
2957
         * Filter the URL for a user's profile editor.
 
2958
         *
 
2959
         * @since 3.1.0
 
2960
         *
 
2961
         * @param string $url     The complete URL including scheme and path.
 
2962
         * @param int    $user_id The user ID.
 
2963
         * @param string $scheme  Scheme to give the URL context. Accepts 'http', 'https', 'login',
 
2964
         *                        'login_post', 'admin', 'relative' or null.
 
2965
         */
 
2966
        return apply_filters( 'edit_profile_url', $url, $user_id, $scheme);
 
2967
}
 
2968
 
 
2969
/**
 
2970
 * Output rel=canonical for singular queries.
 
2971
 *
 
2972
 * @since 2.9.0
 
2973
*/
 
2974
function rel_canonical() {
 
2975
        if ( !is_singular() )
 
2976
                return;
 
2977
 
 
2978
        global $wp_the_query;
 
2979
        if ( !$id = $wp_the_query->get_queried_object_id() )
 
2980
                return;
 
2981
 
 
2982
        $link = get_permalink( $id );
 
2983
 
 
2984
        if ( $page = get_query_var('cpage') )
 
2985
                $link = get_comments_pagenum_link( $page );
 
2986
 
 
2987
        echo "<link rel='canonical' href='$link' />\n";
 
2988
}
 
2989
 
 
2990
/**
 
2991
 * Return a shortlink for a post, page, attachment, or blog.
 
2992
 *
 
2993
 * This function exists to provide a shortlink tag that all themes and plugins can target. A plugin must hook in to
 
2994
 * provide the actual shortlinks. Default shortlink support is limited to providing ?p= style links for posts.
 
2995
 * Plugins can short-circuit this function via the pre_get_shortlink filter or filter the output
 
2996
 * via the get_shortlink filter.
 
2997
 *
 
2998
 * @since 3.0.0.
 
2999
 *
 
3000
 * @param int $id A post or blog id. Default is 0, which means the current post or blog.
 
3001
 * @param string $context Whether the id is a 'blog' id, 'post' id, or 'media' id. If 'post', the post_type of the post is consulted. If 'query', the current query is consulted to determine the id and context. Default is 'post'.
 
3002
 * @param bool $allow_slugs Whether to allow post slugs in the shortlink. It is up to the plugin how and whether to honor this.
 
3003
 * @return string A shortlink or an empty string if no shortlink exists for the requested resource or if shortlinks are not enabled.
 
3004
 */
 
3005
function wp_get_shortlink($id = 0, $context = 'post', $allow_slugs = true) {
 
3006
        /**
 
3007
         * Filter whether to preempt generating a shortlink for the given post.
 
3008
         *
 
3009
         * Passing a truthy value to the filter will effectively short-circuit the
 
3010
         * shortlink-generation process, returning that value instead.
 
3011
         *
 
3012
         * @since 3.0.0
 
3013
         *
 
3014
         * @param bool|string $return      Short-circuit return value. Either false or a URL string.
 
3015
         * @param int         $id          Post ID, or 0 for the current post.
 
3016
         * @param string      $context     The context for the link. One of 'post' or 'query',
 
3017
         * @param bool        $allow_slugs Whether to allow post slugs in the shortlink.
 
3018
         */
 
3019
        $shortlink = apply_filters( 'pre_get_shortlink', false, $id, $context, $allow_slugs );
 
3020
 
 
3021
        if ( false !== $shortlink )
 
3022
                return $shortlink;
 
3023
 
 
3024
        global $wp_query;
 
3025
        $post_id = 0;
 
3026
        if ( 'query' == $context && is_singular() ) {
 
3027
                $post_id = $wp_query->get_queried_object_id();
 
3028
                $post = get_post( $post_id );
 
3029
        } elseif ( 'post' == $context ) {
 
3030
                $post = get_post( $id );
 
3031
                if ( ! empty( $post->ID ) )
 
3032
                        $post_id = $post->ID;
 
3033
        }
 
3034
 
 
3035
        $shortlink = '';
 
3036
 
 
3037
        // Return p= link for all public post types.
 
3038
        if ( ! empty( $post_id ) ) {
 
3039
                $post_type = get_post_type_object( $post->post_type );
 
3040
 
 
3041
                if ( 'page' === $post->post_type && $post->ID == get_option( 'page_on_front' ) && 'page' == get_option( 'show_on_front' ) ) {
 
3042
                        $shortlink = home_url( '/' );
 
3043
                } elseif ( $post_type->public ) {
 
3044
                        $shortlink = home_url( '?p=' . $post_id );
 
3045
                }
 
3046
        }
 
3047
 
 
3048
        /**
 
3049
         * Filter the shortlink for a post.
 
3050
         *
 
3051
         * @since 3.0.0
 
3052
         *
 
3053
         * @param string $shortlink   Shortlink URL.
 
3054
         * @param int    $id          Post ID, or 0 for the current post.
 
3055
         * @param string $context     The context for the link. One of 'post' or 'query',
 
3056
         * @param bool   $allow_slugs Whether to allow post slugs in the shortlink. Not used by default.
 
3057
         */
 
3058
        return apply_filters( 'get_shortlink', $shortlink, $id, $context, $allow_slugs );
 
3059
}
 
3060
 
 
3061
/**
 
3062
 *  Inject rel=shortlink into head if a shortlink is defined for the current page.
 
3063
 *
 
3064
 *  Attached to the wp_head action.
 
3065
 *
 
3066
 * @since 3.0.0
 
3067
 *
 
3068
 * @uses wp_get_shortlink()
 
3069
 */
 
3070
function wp_shortlink_wp_head() {
 
3071
        $shortlink = wp_get_shortlink( 0, 'query' );
 
3072
 
 
3073
        if ( empty( $shortlink ) )
 
3074
                return;
 
3075
 
 
3076
        echo "<link rel='shortlink' href='" . esc_url( $shortlink ) . "' />\n";
 
3077
}
 
3078
 
 
3079
/**
 
3080
 * Send a Link: rel=shortlink header if a shortlink is defined for the current page.
 
3081
 *
 
3082
 * Attached to the wp action.
 
3083
 *
 
3084
 * @since 3.0.0
 
3085
 *
 
3086
 * @uses wp_get_shortlink()
 
3087
 */
 
3088
function wp_shortlink_header() {
 
3089
        if ( headers_sent() )
 
3090
                return;
 
3091
 
 
3092
        $shortlink = wp_get_shortlink(0, 'query');
 
3093
 
 
3094
        if ( empty($shortlink) )
 
3095
                return;
 
3096
 
 
3097
        header('Link: <' . $shortlink . '>; rel=shortlink', false);
 
3098
}
 
3099
 
 
3100
/**
 
3101
 * Display the Short Link for a Post
 
3102
 *
 
3103
 * Must be called from inside "The Loop"
 
3104
 *
 
3105
 * Call like the_shortlink(__('Shortlinkage FTW'))
 
3106
 *
 
3107
 * @since 3.0.0
 
3108
 *
 
3109
 * @param string $text Optional The link text or HTML to be displayed. Defaults to 'This is the short link.'
 
3110
 * @param string $title Optional The tooltip for the link. Must be sanitized. Defaults to the sanitized post title.
 
3111
 * @param string $before Optional HTML to display before the link.
 
3112
 * @param string $after Optional HTML to display after the link.
 
3113
 */
 
3114
function the_shortlink( $text = '', $title = '', $before = '', $after = '' ) {
 
3115
        $post = get_post();
 
3116
 
 
3117
        if ( empty( $text ) )
 
3118
                $text = __('This is the short link.');
 
3119
 
 
3120
        if ( empty( $title ) )
 
3121
                $title = the_title_attribute( array( 'echo' => false ) );
 
3122
 
 
3123
        $shortlink = wp_get_shortlink( $post->ID );
 
3124
 
 
3125
        if ( !empty( $shortlink ) ) {
 
3126
                $link = '<a rel="shortlink" href="' . esc_url( $shortlink ) . '" title="' . $title . '">' . $text . '</a>';
 
3127
 
 
3128
                /**
 
3129
                 * Filter the shortlink anchor tag for a post.
 
3130
                 *
 
3131
                 * @since 3.0.0
 
3132
                 *
 
3133
                 * @param string $link      Shortlink anchor tag.
 
3134
                 * @param string $shortlink Shortlink URL.
 
3135
                 * @param string $text      Shortlink's text.
 
3136
                 * @param string $title     Shortlink's title attribute.
 
3137
                 */
 
3138
                $link = apply_filters( 'the_shortlink', $link, $shortlink, $text, $title );
 
3139
                echo $before, $link, $after;
 
3140
        }
 
3141
}