Version Description
If you're using a caching plugin, flushing its cache right after installing / upgrading to this version is required.
- Fixes a compatibility issue with WordPress 5.5.
- Widget themes: various fixes for better IE11 compatibility.
Release notes
Download this release
Release Info
Developer | hcabrera |
Plugin | WordPress Popular Posts |
Version | 5.2.3 |
Comparing to | |
See all releases |
Code changes from version 5.2.2 to 5.2.3
- assets/themes/cards/style.css +63 -62
- assets/themes/cardview-compact/style.css +72 -71
- assets/themes/cardview/style.css +76 -75
- readme.txt +11 -2
- src/Front/Front.php +474 -460
- src/Image.php +806 -806
- wordpress-popular-posts.php +60 -60
assets/themes/cards/style.css
CHANGED
@@ -1,63 +1,64 @@
|
|
1 |
-
.wpp-cards {
|
2 |
-
margin-left: 0;
|
3 |
-
margin-right: 0;
|
4 |
-
padding: 0;
|
5 |
-
}
|
6 |
-
|
7 |
-
.wpp-cards li {
|
8 |
-
display: flex;
|
9 |
-
list-style: none;
|
10 |
-
margin: 0 0 1.2em 0;
|
11 |
-
padding: 0 0 1em 0;
|
12 |
-
border-bottom: #ddd 1px solid;
|
13 |
-
}
|
14 |
-
|
15 |
-
.wpp-cards li:last-of-type,
|
16 |
-
.wpp-cards li:only-child {
|
17 |
-
margin: 0;
|
18 |
-
padding: 0;
|
19 |
-
border-bottom: none;
|
20 |
-
}
|
21 |
-
|
22 |
-
.wpp-cards li .wpp-thumbnail {
|
23 |
-
overflow: hidden;
|
24 |
-
display: inline-block;
|
25 |
-
|
26 |
-
flex-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
.wpp-cards li .
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
Â
|
|
63 |
Â
}
|
1 |
+
.wpp-cards {
|
2 |
+
margin-left: 0;
|
3 |
+
margin-right: 0;
|
4 |
+
padding: 0;
|
5 |
+
}
|
6 |
+
|
7 |
+
.wpp-cards li {
|
8 |
+
display: flex;
|
9 |
+
list-style: none;
|
10 |
+
margin: 0 0 1.2em 0;
|
11 |
+
padding: 0 0 1em 0;
|
12 |
+
border-bottom: #ddd 1px solid;
|
13 |
+
}
|
14 |
+
|
15 |
+
.wpp-cards li:last-of-type,
|
16 |
+
.wpp-cards li:only-child {
|
17 |
+
margin: 0;
|
18 |
+
padding: 0;
|
19 |
+
border-bottom: none;
|
20 |
+
}
|
21 |
+
|
22 |
+
.wpp-cards li .wpp-thumbnail {
|
23 |
+
overflow: hidden;
|
24 |
+
display: inline-block;
|
25 |
+
align-self: flex-start;
|
26 |
+
flex-grow: 0;
|
27 |
+
flex-shrink: 0;
|
28 |
+
margin-right: 1em;
|
29 |
+
font-size: 0.8em;
|
30 |
+
line-height: 1;
|
31 |
+
background: #f0f0f0;
|
32 |
+
border: none;
|
33 |
+
}
|
34 |
+
|
35 |
+
.wpp-cards li a {
|
36 |
+
text-decoration: none;
|
37 |
+
}
|
38 |
+
|
39 |
+
.wpp-cards li a:hover {
|
40 |
+
text-decoration: underline;
|
41 |
+
}
|
42 |
+
|
43 |
+
.wpp-cards li .taxonomies,
|
44 |
+
.wpp-cards li .wpp-post-title {
|
45 |
+
display: block;
|
46 |
+
font-weight: bold;
|
47 |
+
}
|
48 |
+
|
49 |
+
.wpp-cards li .taxonomies {
|
50 |
+
margin-bottom: 0.25em;
|
51 |
+
font-size: 0.7em;
|
52 |
+
line-height: 1;
|
53 |
+
}
|
54 |
+
|
55 |
+
.wpp-cards li .wpp-post-title {
|
56 |
+
margin-bottom: 0.5em;
|
57 |
+
font-size: 1.2em;
|
58 |
+
line-height: 1.2;
|
59 |
+
}
|
60 |
+
|
61 |
+
.wpp-cards li .wpp-excerpt {
|
62 |
+
margin: 0;
|
63 |
+
font-size: 0.8em;
|
64 |
Â
}
|
assets/themes/cardview-compact/style.css
CHANGED
@@ -1,71 +1,72 @@
|
|
1 |
-
.wpp-cardview-compact {
|
2 |
-
margin-left: 0;
|
3 |
-
margin-right: 0;
|
4 |
-
padding: 0;
|
5 |
-
}
|
6 |
-
|
7 |
-
.wpp-cardview-compact li {
|
8 |
-
list-style: none;
|
9 |
-
margin: 0 0 1.2em 0;
|
10 |
-
padding: 0 0 1em 0;
|
11 |
-
border-bottom: #ddd 1px solid;
|
12 |
-
}
|
13 |
-
|
14 |
-
.wpp-cardview-compact li:last-of-type,
|
15 |
-
.wpp-cardview-compact li:only-child {
|
16 |
-
margin: 0;
|
17 |
-
padding: 0;
|
18 |
-
border-bottom: none;
|
19 |
-
}
|
20 |
-
|
21 |
-
.wpp-cardview-compact .wpp-thumbnail-container {
|
22 |
-
position: relative;
|
23 |
-
margin-bottom: .8em;
|
24 |
-
}
|
25 |
-
|
26 |
-
.wpp-cardview-compact li .wpp-thumbnail {
|
27 |
-
overflow: hidden;
|
28 |
-
display: block;
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
.wpp-cardview-compact li .
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
Â
|
1 |
+
.wpp-cardview-compact {
|
2 |
+
margin-left: 0;
|
3 |
+
margin-right: 0;
|
4 |
+
padding: 0;
|
5 |
+
}
|
6 |
+
|
7 |
+
.wpp-cardview-compact li {
|
8 |
+
list-style: none;
|
9 |
+
margin: 0 0 1.2em 0;
|
10 |
+
padding: 0 0 1em 0;
|
11 |
+
border-bottom: #ddd 1px solid;
|
12 |
+
}
|
13 |
+
|
14 |
+
.wpp-cardview-compact li:last-of-type,
|
15 |
+
.wpp-cardview-compact li:only-child {
|
16 |
+
margin: 0;
|
17 |
+
padding: 0;
|
18 |
+
border-bottom: none;
|
19 |
+
}
|
20 |
+
|
21 |
+
.wpp-cardview-compact .wpp-thumbnail-container {
|
22 |
+
position: relative;
|
23 |
+
margin-bottom: .8em;
|
24 |
+
}
|
25 |
+
|
26 |
+
.wpp-cardview-compact li .wpp-thumbnail {
|
27 |
+
overflow: hidden;
|
28 |
+
display: block;
|
29 |
+
float: none;
|
30 |
+
margin: 0;
|
31 |
+
width: 100%;
|
32 |
+
height: auto;
|
33 |
+
font-size: 0.8em;
|
34 |
+
line-height: 1;
|
35 |
+
background: #f0f0f0;
|
36 |
+
border: none;
|
37 |
+
}
|
38 |
+
|
39 |
+
.wpp-cardview-compact li a {
|
40 |
+
text-decoration: none;
|
41 |
+
}
|
42 |
+
|
43 |
+
.wpp-cardview-compact li a:hover {
|
44 |
+
text-decoration: underline;
|
45 |
+
}
|
46 |
+
|
47 |
+
.wpp-cardview-compact li .taxonomies,
|
48 |
+
.wpp-cardview-compact li .wpp-post-title {
|
49 |
+
display: block;
|
50 |
+
font-weight: bold;
|
51 |
+
}
|
52 |
+
|
53 |
+
.wpp-cardview-compact li .taxonomies {
|
54 |
+
position: absolute;
|
55 |
+
bottom: 0;
|
56 |
+
left: 0;
|
57 |
+
padding: 1em;
|
58 |
+
color: #aaa;
|
59 |
+
font-size: 0.7em;
|
60 |
+
line-height: 1;
|
61 |
+
background: rgba(0, 0, 0, 0.5);
|
62 |
+
}
|
63 |
+
|
64 |
+
.wpp-cardview-compact li .taxonomies a {
|
65 |
+
color: #fff;
|
66 |
+
}
|
67 |
+
|
68 |
+
.wpp-cardview-compact li .wpp-post-title {
|
69 |
+
margin: 0 0 0.5em;
|
70 |
+
font-size: 1.2em;
|
71 |
+
line-height: 1.2;
|
72 |
+
}
|
assets/themes/cardview/style.css
CHANGED
@@ -1,76 +1,77 @@
|
|
1 |
-
.wpp-cardview {
|
2 |
-
margin-left: 0;
|
3 |
-
margin-right: 0;
|
4 |
-
padding: 0;
|
5 |
-
}
|
6 |
-
|
7 |
-
.wpp-cardview li {
|
8 |
-
list-style: none;
|
9 |
-
margin: 0 0 1.2em 0;
|
10 |
-
padding: 0 0 1em 0;
|
11 |
-
border-bottom: #ddd 1px solid;
|
12 |
-
}
|
13 |
-
|
14 |
-
.wpp-cardview li:last-of-type,
|
15 |
-
.wpp-cardview li:only-child {
|
16 |
-
margin: 0;
|
17 |
-
padding: 0;
|
18 |
-
border-bottom: none;
|
19 |
-
}
|
20 |
-
|
21 |
-
.wpp-cardview .wpp-thumbnail-container {
|
22 |
-
position: relative;
|
23 |
-
margin-bottom: .8em;
|
24 |
-
}
|
25 |
-
|
26 |
-
.wpp-cardview li .wpp-thumbnail {
|
27 |
-
overflow: hidden;
|
28 |
-
display: block;
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
.wpp-cardview li .
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
Â
|
|
76 |
Â
}
|
1 |
+
.wpp-cardview {
|
2 |
+
margin-left: 0;
|
3 |
+
margin-right: 0;
|
4 |
+
padding: 0;
|
5 |
+
}
|
6 |
+
|
7 |
+
.wpp-cardview li {
|
8 |
+
list-style: none;
|
9 |
+
margin: 0 0 1.2em 0;
|
10 |
+
padding: 0 0 1em 0;
|
11 |
+
border-bottom: #ddd 1px solid;
|
12 |
+
}
|
13 |
+
|
14 |
+
.wpp-cardview li:last-of-type,
|
15 |
+
.wpp-cardview li:only-child {
|
16 |
+
margin: 0;
|
17 |
+
padding: 0;
|
18 |
+
border-bottom: none;
|
19 |
+
}
|
20 |
+
|
21 |
+
.wpp-cardview .wpp-thumbnail-container {
|
22 |
+
position: relative;
|
23 |
+
margin-bottom: .8em;
|
24 |
+
}
|
25 |
+
|
26 |
+
.wpp-cardview li .wpp-thumbnail {
|
27 |
+
overflow: hidden;
|
28 |
+
display: block;
|
29 |
+
float: none;
|
30 |
+
margin: 0;
|
31 |
+
width: 100%;
|
32 |
+
height: auto;
|
33 |
+
font-size: 0.8em;
|
34 |
+
line-height: 1;
|
35 |
+
background: #f0f0f0;
|
36 |
+
border: none;
|
37 |
+
}
|
38 |
+
|
39 |
+
.wpp-cardview li a {
|
40 |
+
text-decoration: none;
|
41 |
+
}
|
42 |
+
|
43 |
+
.wpp-cardview li a:hover {
|
44 |
+
text-decoration: underline;
|
45 |
+
}
|
46 |
+
|
47 |
+
.wpp-cardview li .taxonomies,
|
48 |
+
.wpp-cardview li .wpp-post-title {
|
49 |
+
display: block;
|
50 |
+
font-weight: bold;
|
51 |
+
}
|
52 |
+
|
53 |
+
.wpp-cardview li .taxonomies {
|
54 |
+
position: absolute;
|
55 |
+
bottom: 0;
|
56 |
+
left: 0;
|
57 |
+
padding: 1em;
|
58 |
+
color: #aaa;
|
59 |
+
font-size: 0.7em;
|
60 |
+
line-height: 1;
|
61 |
+
background: rgba(0, 0, 0, 0.5);
|
62 |
+
}
|
63 |
+
|
64 |
+
.wpp-cardview li .taxonomies a {
|
65 |
+
color: #fff;
|
66 |
+
}
|
67 |
+
|
68 |
+
.wpp-cardview li .wpp-post-title {
|
69 |
+
margin: 0 0 0.5em;
|
70 |
+
font-size: 1.2em;
|
71 |
+
line-height: 1.2;
|
72 |
+
}
|
73 |
+
|
74 |
+
.wpp-cardview li .wpp-excerpt {
|
75 |
+
margin: 0;
|
76 |
+
font-size: 0.8em;
|
77 |
Â
}
|
readme.txt
CHANGED
@@ -3,9 +3,9 @@ Contributors: hcabrera
|
|
3 |
Â
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=hcabrerab%40gmail%2ecom&lc=GB&item_name=WordPress%20Popular%20Posts%20Plugin¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG_global%2egif%3aNonHosted
|
4 |
Â
Tags: popular, posts, widget, popularity, top
|
5 |
Â
Requires at least: 4.9
|
6 |
-
Tested up to: 5.
|
7 |
Â
Requires PHP: 5.4
|
8 |
-
Stable tag: 5.2.
|
9 |
Â
License: GPLv2 or later
|
10 |
Â
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
Â
|
@@ -90,6 +90,15 @@ The FAQ section has been moved [here](https://github.com/cabrerahector/wordpress
|
|
90 |
Â
4. Statistics panel.
|
91 |
Â
|
92 |
Â
== Changelog ==
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
93 |
Â
= 5.2.2 =
|
94 |
Â
|
95 |
Â
**If you're using a caching plugin, flushing its cache right after installing / upgrading to this version is required.**
|
3 |
Â
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=hcabrerab%40gmail%2ecom&lc=GB&item_name=WordPress%20Popular%20Posts%20Plugin¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG_global%2egif%3aNonHosted
|
4 |
Â
Tags: popular, posts, widget, popularity, top
|
5 |
Â
Requires at least: 4.9
|
6 |
+
Tested up to: 5.5
|
7 |
Â
Requires PHP: 5.4
|
8 |
+
Stable tag: 5.2.3
|
9 |
Â
License: GPLv2 or later
|
10 |
Â
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
11 |
Â
|
90 |
Â
4. Statistics panel.
|
91 |
Â
|
92 |
Â
== Changelog ==
|
93 |
+
= 5.2.3 =
|
94 |
+
|
95 |
+
**If you're using a caching plugin, flushing its cache right after installing / upgrading to this version is required.**
|
96 |
+
|
97 |
+
- Fixes a compatibility issue with WordPress 5.5.
|
98 |
+
- Widget themes: various fixes for better IE11 compatibility.
|
99 |
+
|
100 |
+
[Release notes](https://cabrerahector.com/wordpress/wordpress-popular-posts-5-2-is-here#hotfixes-and-minor-updates)
|
101 |
+
|
102 |
Â
= 5.2.2 =
|
103 |
Â
|
104 |
Â
**If you're using a caching plugin, flushing its cache right after installing / upgrading to this version is required.**
|
src/Front/Front.php
CHANGED
@@ -1,460 +1,474 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* The public-facing functionality of the plugin.
|
4 |
-
*
|
5 |
-
* Defines hooks to enqueue the public-specific stylesheet and JavaScript.
|
6 |
-
*
|
7 |
-
* @package WordPressPopularPosts
|
8 |
-
* @subpackage WordPressPopularPosts/Front
|
9 |
-
* @author Hector Cabrera <me@cabrerahector.com>
|
10 |
-
*/
|
11 |
-
|
12 |
-
namespace WordPressPopularPosts\Front;
|
13 |
-
|
14 |
-
use WordPressPopularPosts\Helper;
|
15 |
-
use WordPressPopularPosts\Output;
|
16 |
-
use WordPressPopularPosts\Query;
|
17 |
-
|
18 |
-
class Front {
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Plugin options.
|
22 |
-
*
|
23 |
-
* @var array $config
|
24 |
-
* @access private
|
25 |
-
*/
|
26 |
-
private $config;
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Translate object.
|
30 |
-
*
|
31 |
-
* @var \WordPressPopularPosts\Translate $translate
|
32 |
-
* @access private
|
33 |
-
*/
|
34 |
-
private $translate;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Output object.
|
38 |
-
*
|
39 |
-
* @var \WordPressPopularPosts\Output $output
|
40 |
-
* @access private
|
41 |
-
*/
|
42 |
-
private $output;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Construct.
|
46 |
-
*
|
47 |
-
* @since 5.0.0
|
48 |
-
* @param array $config Admin settings.
|
49 |
-
* @param \WordPressPopularPosts\Translate $translate Translate class.
|
50 |
-
*/
|
51 |
-
public function __construct(array $config, \WordPressPopularPosts\Translate $translate, \WordPressPopularPosts\Output $output)
|
52 |
-
{
|
53 |
-
$this->config = $config;
|
54 |
-
$this->translate = $translate;
|
55 |
-
$this->output = $output;
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* WordPress public-facing hooks.
|
60 |
-
*
|
61 |
-
* @since 5.0.0
|
62 |
-
*/
|
63 |
-
public function hooks()
|
64 |
-
{
|
65 |
-
add_shortcode('wpp', [$this, 'wpp_shortcode']);
|
66 |
-
add_action('wp_ajax_update_views_ajax', [$this, 'update_views']);
|
67 |
-
add_action('wp_ajax_nopriv_update_views_ajax', [$this, 'update_views']);
|
68 |
-
add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
|
69 |
-
add_filter('script_loader_tag', [$this, 'convert_inline_js_into_json'], 10, 3);
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Enqueues public facing assets.
|
74 |
-
*
|
75 |
-
* @since 5.0.0
|
76 |
-
*/
|
77 |
-
public function enqueue_assets()
|
78 |
-
{
|
79 |
-
// Enqueue WPP's stylesheet.
|
80 |
-
if ( $this->config['tools']['css'] ) {
|
81 |
-
$theme_file = get_stylesheet_directory() . '/wpp.css';
|
82 |
-
|
83 |
-
if ( @is_file($theme_file) ) {
|
84 |
-
wp_enqueue_style('wordpress-popular-posts-css', get_stylesheet_directory_uri() . "/wpp.css", [], WPP_VERSION, 'all');
|
85 |
-
} // Load stock stylesheet
|
86 |
-
else {
|
87 |
-
wp_enqueue_style('wordpress-popular-posts-css', plugin_dir_url(dirname(dirname(__FILE__))) . 'assets/css/wpp.css', [], WPP_VERSION, 'all');
|
88 |
-
}
|
89 |
-
}
|
90 |
-
|
91 |
-
// Enqueue WPP's library.
|
92 |
-
$is_single = 0;
|
93 |
-
|
94 |
-
if (
|
95 |
-
( 0 == $this->config['tools']['log']['level'] && ! is_user_logged_in() )
|
96 |
-
|| ( 1 == $this->config['tools']['log']['level'] )
|
97 |
-
|| ( 2 == $this->config['tools']['log']['level'] && is_user_logged_in() )
|
98 |
-
) {
|
99 |
-
$is_single = Helper::is_single();
|
100 |
-
}
|
101 |
-
|
102 |
-
wp_register_script('wpp-js', plugin_dir_url(dirname(dirname(__FILE__))) . 'assets/js/wpp.min.js', [], WPP_VERSION, false);
|
103 |
-
$params = [
|
104 |
-
'sampling_active' => (int) $this->config['tools']['sampling']['active'],
|
105 |
-
'sampling_rate' => (int) $this->config['tools']['sampling']['rate'],
|
106 |
-
'ajax_url' => esc_url_raw(rest_url('wordpress-popular-posts/v1/popular-posts')),
|
107 |
-
'ID' => (int) $is_single,
|
108 |
-
'token' => wp_create_nonce('wp_rest'),
|
109 |
-
'lang' => function_exists('PLL') ? $this->translate->get_current_language() : 0,
|
110 |
-
'debug' => (int) WP_DEBUG
|
111 |
-
];
|
112 |
-
wp_enqueue_script('wpp-js');
|
113 |
-
wp_add_inline_script('wpp-js', json_encode($params), 'before');
|
114 |
-
}
|
115 |
-
|
116 |
-
/**
|
117 |
-
* Converts inline script tag into type=application/json.
|
118 |
-
*
|
119 |
-
* This function mods the original script tag as printed
|
120 |
-
* by WordPress which contains the data for the wpp_params
|
121 |
-
* object into a JSON script. This improves compatibility
|
122 |
-
* with Content Security Policy (CSP).
|
123 |
-
*
|
124 |
-
* @since 5.2.0
|
125 |
-
* @param string $tag
|
126 |
-
* @param string $handle
|
127 |
-
* @param string $src
|
128 |
-
* @return string $tag
|
129 |
-
*/
|
130 |
-
function convert_inline_js_into_json($tag, $handle, $src)
|
131 |
-
{
|
132 |
-
if ( 'wpp-js' === $handle ) {
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
}
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
//
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
))
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
$
|
228 |
-
$
|
229 |
-
$now,
|
230 |
-
$views,
|
231 |
-
$
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
* @var
|
269 |
-
* @var int $
|
270 |
-
* @var int $
|
271 |
-
* @var
|
272 |
-
* @var bool $
|
273 |
-
* @var
|
274 |
-
* @var
|
275 |
-
* @var
|
276 |
-
* @var string $
|
277 |
-
* @var
|
278 |
-
* @var
|
279 |
-
* @var
|
280 |
-
* @var
|
281 |
-
* @var
|
282 |
-
* @var
|
283 |
-
* @var
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
'
|
301 |
-
'
|
302 |
-
'
|
303 |
-
'
|
304 |
-
'
|
305 |
-
'
|
306 |
-
'
|
307 |
-
'
|
308 |
-
'
|
309 |
-
'
|
310 |
-
'
|
311 |
-
'
|
312 |
-
'
|
313 |
-
'
|
314 |
-
'
|
315 |
-
'
|
316 |
-
'
|
317 |
-
'
|
318 |
-
'
|
319 |
-
'
|
320 |
-
'
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
'
|
330 |
-
'
|
331 |
-
'
|
332 |
-
'
|
333 |
-
'
|
334 |
-
'
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
'
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
'
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
],
|
354 |
-
'
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
'
|
364 |
-
'
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
'
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
'
|
375 |
-
'
|
376 |
-
'
|
377 |
-
'
|
378 |
-
'
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
//
|
399 |
-
$ids = array_filter(explode(
|
400 |
-
// Got no valid IDs, clear
|
401 |
-
if ( empty($ids) ) {
|
402 |
-
$shortcode_ops['
|
403 |
-
}
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
//
|
408 |
-
if (
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
}
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* The public-facing functionality of the plugin.
|
4 |
+
*
|
5 |
+
* Defines hooks to enqueue the public-specific stylesheet and JavaScript.
|
6 |
+
*
|
7 |
+
* @package WordPressPopularPosts
|
8 |
+
* @subpackage WordPressPopularPosts/Front
|
9 |
+
* @author Hector Cabrera <me@cabrerahector.com>
|
10 |
+
*/
|
11 |
+
|
12 |
+
namespace WordPressPopularPosts\Front;
|
13 |
+
|
14 |
+
use WordPressPopularPosts\Helper;
|
15 |
+
use WordPressPopularPosts\Output;
|
16 |
+
use WordPressPopularPosts\Query;
|
17 |
+
|
18 |
+
class Front {
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Plugin options.
|
22 |
+
*
|
23 |
+
* @var array $config
|
24 |
+
* @access private
|
25 |
+
*/
|
26 |
+
private $config;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Translate object.
|
30 |
+
*
|
31 |
+
* @var \WordPressPopularPosts\Translate $translate
|
32 |
+
* @access private
|
33 |
+
*/
|
34 |
+
private $translate;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Output object.
|
38 |
+
*
|
39 |
+
* @var \WordPressPopularPosts\Output $output
|
40 |
+
* @access private
|
41 |
+
*/
|
42 |
+
private $output;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Construct.
|
46 |
+
*
|
47 |
+
* @since 5.0.0
|
48 |
+
* @param array $config Admin settings.
|
49 |
+
* @param \WordPressPopularPosts\Translate $translate Translate class.
|
50 |
+
*/
|
51 |
+
public function __construct(array $config, \WordPressPopularPosts\Translate $translate, \WordPressPopularPosts\Output $output)
|
52 |
+
{
|
53 |
+
$this->config = $config;
|
54 |
+
$this->translate = $translate;
|
55 |
+
$this->output = $output;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* WordPress public-facing hooks.
|
60 |
+
*
|
61 |
+
* @since 5.0.0
|
62 |
+
*/
|
63 |
+
public function hooks()
|
64 |
+
{
|
65 |
+
add_shortcode('wpp', [$this, 'wpp_shortcode']);
|
66 |
+
add_action('wp_ajax_update_views_ajax', [$this, 'update_views']);
|
67 |
+
add_action('wp_ajax_nopriv_update_views_ajax', [$this, 'update_views']);
|
68 |
+
add_action('wp_enqueue_scripts', [$this, 'enqueue_assets']);
|
69 |
+
add_filter('script_loader_tag', [$this, 'convert_inline_js_into_json'], 10, 3);
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Enqueues public facing assets.
|
74 |
+
*
|
75 |
+
* @since 5.0.0
|
76 |
+
*/
|
77 |
+
public function enqueue_assets()
|
78 |
+
{
|
79 |
+
// Enqueue WPP's stylesheet.
|
80 |
+
if ( $this->config['tools']['css'] ) {
|
81 |
+
$theme_file = get_stylesheet_directory() . '/wpp.css';
|
82 |
+
|
83 |
+
if ( @is_file($theme_file) ) {
|
84 |
+
wp_enqueue_style('wordpress-popular-posts-css', get_stylesheet_directory_uri() . "/wpp.css", [], WPP_VERSION, 'all');
|
85 |
+
} // Load stock stylesheet
|
86 |
+
else {
|
87 |
+
wp_enqueue_style('wordpress-popular-posts-css', plugin_dir_url(dirname(dirname(__FILE__))) . 'assets/css/wpp.css', [], WPP_VERSION, 'all');
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
// Enqueue WPP's library.
|
92 |
+
$is_single = 0;
|
93 |
+
|
94 |
+
if (
|
95 |
+
( 0 == $this->config['tools']['log']['level'] && ! is_user_logged_in() )
|
96 |
+
|| ( 1 == $this->config['tools']['log']['level'] )
|
97 |
+
|| ( 2 == $this->config['tools']['log']['level'] && is_user_logged_in() )
|
98 |
+
) {
|
99 |
+
$is_single = Helper::is_single();
|
100 |
+
}
|
101 |
+
|
102 |
+
wp_register_script('wpp-js', plugin_dir_url(dirname(dirname(__FILE__))) . 'assets/js/wpp.min.js', [], WPP_VERSION, false);
|
103 |
+
$params = [
|
104 |
+
'sampling_active' => (int) $this->config['tools']['sampling']['active'],
|
105 |
+
'sampling_rate' => (int) $this->config['tools']['sampling']['rate'],
|
106 |
+
'ajax_url' => esc_url_raw(rest_url('wordpress-popular-posts/v1/popular-posts')),
|
107 |
+
'ID' => (int) $is_single,
|
108 |
+
'token' => wp_create_nonce('wp_rest'),
|
109 |
+
'lang' => function_exists('PLL') ? $this->translate->get_current_language() : 0,
|
110 |
+
'debug' => (int) WP_DEBUG
|
111 |
+
];
|
112 |
+
wp_enqueue_script('wpp-js');
|
113 |
+
wp_add_inline_script('wpp-js', json_encode($params), 'before');
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Converts inline script tag into type=application/json.
|
118 |
+
*
|
119 |
+
* This function mods the original script tag as printed
|
120 |
+
* by WordPress which contains the data for the wpp_params
|
121 |
+
* object into a JSON script. This improves compatibility
|
122 |
+
* with Content Security Policy (CSP).
|
123 |
+
*
|
124 |
+
* @since 5.2.0
|
125 |
+
* @param string $tag
|
126 |
+
* @param string $handle
|
127 |
+
* @param string $src
|
128 |
+
* @return string $tag
|
129 |
+
*/
|
130 |
+
function convert_inline_js_into_json($tag, $handle, $src)
|
131 |
+
{
|
132 |
+
if ( 'wpp-js' === $handle ) {
|
133 |
+
// id attribute found, replace it
|
134 |
+
if ( false !== strpos($tag, 'wpp-js-js-before') ) {
|
135 |
+
$tag = str_replace('wpp-js-js-before', 'wpp-json', $tag);
|
136 |
+
} // id attribute missing, let's add it
|
137 |
+
else {
|
138 |
+
$pos = strpos($tag, '>');
|
139 |
+
$tag = substr_replace($tag, ' id="wpp-json">', $pos, 1);
|
140 |
+
}
|
141 |
+
|
142 |
+
// type attribute found, replace it
|
143 |
+
if ( false !== strpos($tag, 'type') ) {
|
144 |
+
$pos = strpos($tag, 'text/javascript');
|
145 |
+
|
146 |
+
if ( false !== $pos )
|
147 |
+
$tag = substr_replace($tag, 'application/json', $pos, strlen('text/javascript'));
|
148 |
+
} // type attribute missing, let's add it
|
149 |
+
else {
|
150 |
+
$pos = strpos($tag, '>');
|
151 |
+
$tag = substr_replace($tag, ' type="application/json">', $pos, 1);
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
return $tag;
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Updates views count on page load via AJAX.
|
160 |
+
*
|
161 |
+
* @since 2.0.0
|
162 |
+
*/
|
163 |
+
public function update_views()
|
164 |
+
{
|
165 |
+
if ( ! wp_verify_nonce($_POST['token'], 'wpp-token') || ! Helper::is_number($_POST['wpp_id']) ) {
|
166 |
+
die( "WPP: Oops, invalid request!" );
|
167 |
+
}
|
168 |
+
|
169 |
+
$nonce = $_POST['token'];
|
170 |
+
$post_ID = $_POST['wpp_id'];
|
171 |
+
$exec_time = 0;
|
172 |
+
|
173 |
+
$start = Helper::microtime_float();
|
174 |
+
$result = $this->update_views_count($post_ID);
|
175 |
+
$end = Helper::microtime_float();
|
176 |
+
$exec_time += round($end - $start, 6);
|
177 |
+
|
178 |
+
if ( $result ) {
|
179 |
+
die("WPP: OK. Execution time: " . $exec_time . " seconds");
|
180 |
+
}
|
181 |
+
|
182 |
+
die("WPP: Oops, could not update the views count!");
|
183 |
+
}
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Updates views count.
|
187 |
+
*
|
188 |
+
* @since 1.4.0
|
189 |
+
* @access private
|
190 |
+
* @global object $wpdb
|
191 |
+
* @param int $post_ID
|
192 |
+
* @return bool|int FALSE if query failed, TRUE on success
|
193 |
+
*/
|
194 |
+
private function update_views_count($post_ID) {
|
195 |
+
/*
|
196 |
+
TODO:
|
197 |
+
For WordPress Multisite, we must define the DIEONDBERROR constant for database errors to display like so:
|
198 |
+
<?php define( 'DIEONDBERROR', true ); ?>
|
199 |
+
*/
|
200 |
+
global $wpdb;
|
201 |
+
$table = $wpdb->prefix . "popularposts";
|
202 |
+
$wpdb->show_errors();
|
203 |
+
|
204 |
+
// Get translated object ID
|
205 |
+
$post_ID = $this->translate->get_object_id(
|
206 |
+
$post_ID,
|
207 |
+
get_post_type($post_ID),
|
208 |
+
true,
|
209 |
+
$this->translate->get_default_language()
|
210 |
+
);
|
211 |
+
$now = Helper::now();
|
212 |
+
$curdate = Helper::curdate();
|
213 |
+
$views = ( $this->config['tools']['sampling']['active'] )
|
214 |
+
? $this->config['tools']['sampling']['rate']
|
215 |
+
: 1;
|
216 |
+
|
217 |
+
// Allow WP themers / coders perform an action
|
218 |
+
// before updating views count
|
219 |
+
if ( has_action('wpp_pre_update_views') )
|
220 |
+
do_action('wpp_pre_update_views', $post_ID, $views);
|
221 |
+
|
222 |
+
// Update all-time table
|
223 |
+
$result1 = $wpdb->query($wpdb->prepare(
|
224 |
+
"INSERT INTO {$table}data
|
225 |
+
(postid, day, last_viewed, pageviews) VALUES (%d, %s, %s, %d)
|
226 |
+
ON DUPLICATE KEY UPDATE pageviews = pageviews + %d, last_viewed = %s;",
|
227 |
+
$post_ID,
|
228 |
+
$now,
|
229 |
+
$now,
|
230 |
+
$views,
|
231 |
+
$views,
|
232 |
+
$now
|
233 |
+
));
|
234 |
+
|
235 |
+
// Update range (summary) table
|
236 |
+
$result2 = $wpdb->query($wpdb->prepare(
|
237 |
+
"INSERT INTO {$table}summary
|
238 |
+
(postid, pageviews, view_date, view_datetime) VALUES (%d, %d, %s, %s)
|
239 |
+
ON DUPLICATE KEY UPDATE pageviews = pageviews + %d, view_datetime = %s;",
|
240 |
+
$post_ID,
|
241 |
+
$views,
|
242 |
+
$curdate,
|
243 |
+
$now,
|
244 |
+
$views,
|
245 |
+
$now
|
246 |
+
));
|
247 |
+
|
248 |
+
if ( !$result1 || !$result2 )
|
249 |
+
return false;
|
250 |
+
|
251 |
+
// Allow WP themers / coders perform an action
|
252 |
+
// after updating views count
|
253 |
+
if ( has_action('wpp_post_update_views' ))
|
254 |
+
do_action('wpp_post_update_views', $post_ID);
|
255 |
+
|
256 |
+
return true;
|
257 |
+
}
|
258 |
+
|
259 |
+
/**
|
260 |
+
* WPP shortcode handler.
|
261 |
+
*
|
262 |
+
* @since 1.4.0
|
263 |
+
* @param array $atts User defined attributes in shortcode tag
|
264 |
+
* @return string
|
265 |
+
*/
|
266 |
+
public function wpp_shortcode($atts = null) {
|
267 |
+
/**
|
268 |
+
* @var string $header
|
269 |
+
* @var int $limit
|
270 |
+
* @var int $offset
|
271 |
+
* @var string $range
|
272 |
+
* @var bool $freshness
|
273 |
+
* @var string $order_by
|
274 |
+
* @var string $post_type
|
275 |
+
* @var string $pid
|
276 |
+
* @var string $cat
|
277 |
+
* @var string $author
|
278 |
+
* @var int $title_length
|
279 |
+
* @var int $title_by_words
|
280 |
+
* @var int $excerpt_length
|
281 |
+
* @var int $excerpt_format
|
282 |
+
* @var int $excerpt_by_words
|
283 |
+
* @var int $thumbnail_width
|
284 |
+
* @var int $thumbnail_height
|
285 |
+
* @var bool $rating
|
286 |
+
* @var bool $stats_comments
|
287 |
+
* @var bool $stats_views
|
288 |
+
* @var bool $stats_author
|
289 |
+
* @var bool $stats_date
|
290 |
+
* @var string $stats_date_format
|
291 |
+
* @var bool $stats_category
|
292 |
+
* @var string $wpp_start
|
293 |
+
* @var string $wpp_end
|
294 |
+
* @var string $header_start
|
295 |
+
* @var string $header_end
|
296 |
+
* @var string $post_html
|
297 |
+
* @var bool $php
|
298 |
+
*/
|
299 |
+
extract(shortcode_atts([
|
300 |
+
'header' => '',
|
301 |
+
'limit' => 10,
|
302 |
+
'offset' => 0,
|
303 |
+
'range' => 'daily',
|
304 |
+
'time_unit' => 'hour',
|
305 |
+
'time_quantity' => 24,
|
306 |
+
'freshness' => false,
|
307 |
+
'order_by' => 'views',
|
308 |
+
'post_type' => 'post',
|
309 |
+
'pid' => '',
|
310 |
+
'cat' => '',
|
311 |
+
'taxonomy' => 'category',
|
312 |
+
'term_id' => '',
|
313 |
+
'author' => '',
|
314 |
+
'title_length' => 0,
|
315 |
+
'title_by_words' => 0,
|
316 |
+
'excerpt_length' => 0,
|
317 |
+
'excerpt_format' => 0,
|
318 |
+
'excerpt_by_words' => 0,
|
319 |
+
'thumbnail_width' => 0,
|
320 |
+
'thumbnail_height' => 0,
|
321 |
+
'rating' => false,
|
322 |
+
'stats_comments' => false,
|
323 |
+
'stats_views' => true,
|
324 |
+
'stats_author' => false,
|
325 |
+
'stats_date' => false,
|
326 |
+
'stats_date_format' => 'F j, Y',
|
327 |
+
'stats_category' => false,
|
328 |
+
'stats_taxonomy' => false,
|
329 |
+
'wpp_start' => '<ul class="wpp-list">',
|
330 |
+
'wpp_end' => '</ul>',
|
331 |
+
'header_start' => '<h2>',
|
332 |
+
'header_end' => '</h2>',
|
333 |
+
'post_html' => '',
|
334 |
+
'php' => false
|
335 |
+
], $atts, 'wpp'));
|
336 |
+
|
337 |
+
// possible values for "Time Range" and "Order by"
|
338 |
+
$time_units = ["minute", "hour", "day", "week", "month"];
|
339 |
+
$range_values = ["daily", "last24hours", "weekly", "last7days", "monthly", "last30days", "all", "custom"];
|
340 |
+
$order_by_values = ["comments", "views", "avg"];
|
341 |
+
|
342 |
+
$shortcode_ops = [
|
343 |
+
'title' => strip_tags($header),
|
344 |
+
'limit' => ( ! empty($limit ) && Helper::is_number($limit) && $limit > 0 ) ? $limit : 10,
|
345 |
+
'offset' => ( ! empty($offset) && Helper::is_number($offset) && $offset >= 0 ) ? $offset : 0,
|
346 |
+
'range' => ( in_array($range, $range_values) ) ? $range : 'daily',
|
347 |
+
'time_quantity' => ( ! empty($time_quantity ) && Helper::is_number($time_quantity) && $time_quantity > 0 ) ? $time_quantity : 24,
|
348 |
+
'time_unit' => ( in_array($time_unit, $time_units) ) ? $time_unit : 'hour',
|
349 |
+
'freshness' => empty($freshness) ? false : $freshness,
|
350 |
+
'order_by' => ( in_array($order_by, $order_by_values) ) ? $order_by : 'views',
|
351 |
+
'post_type' => empty($post_type) ? 'post,page' : $post_type,
|
352 |
+
'pid' => rtrim(preg_replace('|[^0-9,]|', '', $pid), ","),
|
353 |
+
'cat' => rtrim(preg_replace('|[^0-9,-]|', '', $cat), ","),
|
354 |
+
'taxonomy' => empty($taxonomy) ? 'category' : $taxonomy,
|
355 |
+
'term_id' => rtrim(preg_replace('|[^0-9,;-]|', '', $term_id), ","),
|
356 |
+
'author' => rtrim(preg_replace('|[^0-9,]|', '', $author), ","),
|
357 |
+
'shorten_title' => [
|
358 |
+
'active' => ( ! empty($title_length) && Helper::is_number($title_length) && $title_length > 0 ),
|
359 |
+
'length' => ( ! empty($title_length) && Helper::is_number($title_length) ) ? $title_length : 0,
|
360 |
+
'words' => ( ! empty($title_by_words) && Helper::is_number($title_by_words) && $title_by_words > 0 ),
|
361 |
+
],
|
362 |
+
'post-excerpt' => [
|
363 |
+
'active' => ( ! empty($excerpt_length) && Helper::is_number($excerpt_length) && $excerpt_length > 0 ),
|
364 |
+
'length' => ( ! empty($excerpt_length) && Helper::is_number($excerpt_length) ) ? $excerpt_length : 0,
|
365 |
+
'keep_format' => ( ! empty($excerpt_format) && Helper::is_number($excerpt_format) && $excerpt_format > 0 ),
|
366 |
+
'words' => ( ! empty($excerpt_by_words) && Helper::is_number($excerpt_by_words) && $excerpt_by_words > 0 ),
|
367 |
+
],
|
368 |
+
'thumbnail' => [
|
369 |
+
'active' => ( ! empty($thumbnail_width) && Helper::is_number($thumbnail_width) && $thumbnail_width > 0 ),
|
370 |
+
'width' => ( ! empty($thumbnail_width) && Helper::is_number($thumbnail_width) && $thumbnail_width > 0 ) ? $thumbnail_width : 0,
|
371 |
+
'height' => ( ! empty($thumbnail_height) && Helper::is_number($thumbnail_height) && $thumbnail_height > 0 ) ? $thumbnail_height : 0,
|
372 |
+
],
|
373 |
+
'rating' => empty($rating) ? false : $rating,
|
374 |
+
'stats_tag' => [
|
375 |
+
'comment_count' => empty($stats_comments) ? false : $stats_comments,
|
376 |
+
'views' => empty($stats_views) ? false : $stats_views,
|
377 |
+
'author' => empty($stats_author) ? false : $stats_author,
|
378 |
+
'date' => [
|
379 |
+
'active' => empty($stats_date) ? false : $stats_date,
|
380 |
+
'format' => empty($stats_date_format) ? 'F j, Y' : $stats_date_format
|
381 |
+
],
|
382 |
+
'category' => empty($stats_category) ? false : $stats_category,
|
383 |
+
'taxonomy' => [
|
384 |
+
'active' => empty($stats_taxonomy) ? false : $stats_taxonomy,
|
385 |
+
'name' => empty($taxonomy) ? 'category' : $taxonomy,
|
386 |
+
]
|
387 |
+
],
|
388 |
+
'markup' => [
|
389 |
+
'custom_html' => true,
|
390 |
+
'wpp-start' => empty($wpp_start) ? '' : $wpp_start,
|
391 |
+
'wpp-end' => empty($wpp_end) ? '' : $wpp_end,
|
392 |
+
'title-start' => empty($header_start) ? '' : $header_start,
|
393 |
+
'title-end' => empty($header_end) ? '' : $header_end,
|
394 |
+
'post-html' => empty($post_html) ? '<li>{thumb} {title} <span class="wpp-meta post-stats">{stats}</span></li>' : $post_html
|
395 |
+
]
|
396 |
+
];
|
397 |
+
|
398 |
+
// Post / Page / CTP filter
|
399 |
+
$ids = array_filter(explode(",", $shortcode_ops['pid']), 'is_numeric');
|
400 |
+
// Got no valid IDs, clear
|
401 |
+
if ( empty($ids) ) {
|
402 |
+
$shortcode_ops['pid'] = '';
|
403 |
+
}
|
404 |
+
|
405 |
+
// Category filter
|
406 |
+
$ids = array_filter(explode(",", $shortcode_ops['cat']), 'is_numeric');
|
407 |
+
// Got no valid IDs, clear
|
408 |
+
if ( empty($ids) ) {
|
409 |
+
$shortcode_ops['cat'] = '';
|
410 |
+
}
|
411 |
+
|
412 |
+
// Author filter
|
413 |
+
$ids = array_filter(explode( ",", $shortcode_ops['author']), 'is_numeric');
|
414 |
+
// Got no valid IDs, clear
|
415 |
+
if ( empty($ids) ) {
|
416 |
+
$shortcode_ops['author'] = '';
|
417 |
+
}
|
418 |
+
|
419 |
+
$shortcode_content = '';
|
420 |
+
|
421 |
+
// is there a title defined by user?
|
422 |
+
if (
|
423 |
+
! empty($header)
|
424 |
+
&& ! empty($header_start)
|
425 |
+
&& ! empty($header_end)
|
426 |
+
) {
|
427 |
+
$shortcode_content .= htmlspecialchars_decode($header_start, ENT_QUOTES) . $header . htmlspecialchars_decode($header_end, ENT_QUOTES);
|
428 |
+
}
|
429 |
+
|
430 |
+
$cached = false;
|
431 |
+
|
432 |
+
// Return cached results
|
433 |
+
if ( $this->config['tools']['cache']['active'] ) {
|
434 |
+
|
435 |
+
$key = md5(json_encode($shortcode_ops));
|
436 |
+
$popular_posts = \WordPressPopularPosts\Cache::get($key);
|
437 |
+
|
438 |
+
if ( false === $popular_posts ) {
|
439 |
+
$popular_posts = new Query($shortcode_ops);
|
440 |
+
|
441 |
+
$time_value = $this->config['tools']['cache']['interval']['value']; // eg. 5
|
442 |
+
$time_unit = $this->config['tools']['cache']['interval']['time']; // eg. 'minute'
|
443 |
+
|
444 |
+
// No popular posts found, check again in 1 minute
|
445 |
+
if ( ! $popular_posts->get_posts() ) {
|
446 |
+
$time_value = 1;
|
447 |
+
$time_unit = 'minute';
|
448 |
+
}
|
449 |
+
|
450 |
+
\WordPressPopularPosts\Cache::set(
|
451 |
+
$key,
|
452 |
+
$popular_posts,
|
453 |
+
$time_value,
|
454 |
+
$time_unit
|
455 |
+
);
|
456 |
+
}
|
457 |
+
|
458 |
+
$cached = true;
|
459 |
+
|
460 |
+
} // Get popular posts
|
461 |
+
else {
|
462 |
+
$popular_posts = new Query($shortcode_ops);
|
463 |
+
}
|
464 |
+
|
465 |
+
$this->output->set_data($popular_posts->get_posts());
|
466 |
+
$this->output->set_public_options($shortcode_ops);
|
467 |
+
$this->output->build_output();
|
468 |
+
|
469 |
+
$shortcode_content .= $this->output->get_output();
|
470 |
+
|
471 |
+
return $shortcode_content;
|
472 |
+
}
|
473 |
+
|
474 |
+
}
|
src/Image.php
CHANGED
@@ -1,806 +1,806 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* This class builds/retrieves the thumbnail image of each popular posts.
|
4 |
-
*
|
5 |
-
*
|
6 |
-
* @package WordPressPopularPosts
|
7 |
-
* @author Hector Cabrera <me@cabrerahector.com>
|
8 |
-
*/
|
9 |
-
|
10 |
-
namespace WordPressPopularPosts;
|
11 |
-
|
12 |
-
class Image {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Default thumbnail.
|
16 |
-
*
|
17 |
-
* @since 2.2.0
|
18 |
-
* @var string
|
19 |
-
*/
|
20 |
-
private $default_thumbnail = '';
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Plugin uploads directory.
|
24 |
-
*
|
25 |
-
* @since 3.0.4
|
26 |
-
* @var array
|
27 |
-
*/
|
28 |
-
private $uploads_dir = [];
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Admin settings.
|
32 |
-
*
|
33 |
-
* @since 5.0.0
|
34 |
-
* @var array
|
35 |
-
*/
|
36 |
-
private $admin_options = [];
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Available image sizes.
|
40 |
-
*
|
41 |
-
* @since 5.0.0
|
42 |
-
* @var array
|
43 |
-
*/
|
44 |
-
private $available_sizes = [];
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Construct.
|
48 |
-
*
|
49 |
-
* @since 4.0.0
|
50 |
-
* @param array $admin_options
|
51 |
-
*/
|
52 |
-
public function __construct(array $admin_options)
|
53 |
-
{
|
54 |
-
$this->admin_options = $admin_options;
|
55 |
-
|
56 |
-
// Set default thumbnail
|
57 |
-
$this->default_thumbnail = plugins_url() . "/wordpress-popular-posts/assets/images/no_thumb.jpg";
|
58 |
-
|
59 |
-
if ( $this->is_image_url($this->admin_options['tools']['thumbnail']['default']) )
|
60 |
-
$this->default_thumbnail = $this->admin_options['tools']['thumbnail']['default'];
|
61 |
-
|
62 |
-
// Set uploads folder
|
63 |
-
$wp_upload_dir = wp_get_upload_dir();
|
64 |
-
$this->uploads_dir['basedir'] = $wp_upload_dir['basedir'] . "/" . 'wordpress-popular-posts';
|
65 |
-
$this->uploads_dir['baseurl'] = $wp_upload_dir['baseurl'] . "/" . 'wordpress-popular-posts';
|
66 |
-
|
67 |
-
if ( ! is_dir($this->uploads_dir['basedir']) ) {
|
68 |
-
// Couldn't create the folder, store thumbnails in Uploads
|
69 |
-
if ( ! wp_mkdir_p($this->uploads_dir['basedir']) ) {
|
70 |
-
$this->uploads_dir['basedir'] = $wp_upload_dir['basedir'];
|
71 |
-
$this->uploads_dir['baseurl'] = $wp_upload_dir['baseurl'];
|
72 |
-
}
|
73 |
-
}
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Get WPP's uploads folder.
|
78 |
-
*
|
79 |
-
* @since 4.0.0
|
80 |
-
* @access public
|
81 |
-
* @return array|bool
|
82 |
-
*/
|
83 |
-
public function get_plugin_uploads_dir()
|
84 |
-
{
|
85 |
-
if ( is_array($this->uploads_dir) && ! empty($this->uploads_dir) )
|
86 |
-
return $this->uploads_dir;
|
87 |
-
return false;
|
88 |
-
}
|
89 |
-
|
90 |
-
/**
|
91 |
-
* Returns an image.
|
92 |
-
*
|
93 |
-
* @since 5.0.0
|
94 |
-
* @param \stdClass $post_object Post object
|
95 |
-
* @param array $size Image size (width & height)
|
96 |
-
* @param string $source Image source
|
97 |
-
* @param bool $crop Whether to crop the image or not
|
98 |
-
* @param string $build Whether to build the image or get an existing one
|
99 |
-
* @return string
|
100 |
-
*/
|
101 |
-
public function get($post_object, $size, $source, $crop = true, $build = 'manual')
|
102 |
-
{
|
103 |
-
// Bail, $post_object is not an actual object
|
104 |
-
if ( false === $post_object instanceof \stdClass || ! isset($post_object->id) ) {
|
105 |
-
return '';
|
106 |
-
}
|
107 |
-
|
108 |
-
$alt = '';
|
109 |
-
$classes = ['wpp-thumbnail', 'wpp_' . $source];
|
110 |
-
$filename = $post_object->id . '-' . $source . '-' . $size[0] . 'x' . $size[1];
|
111 |
-
$cached = $this->exists($filename);
|
112 |
-
|
113 |
-
// We have a thumbnail already, return it
|
114 |
-
if ( $cached ) {
|
115 |
-
$classes[] = 'wpp_cached_thumb';
|
116 |
-
|
117 |
-
/**
|
118 |
-
* Filters CSS classes assigned to the thumbnail
|
119 |
-
*
|
120 |
-
* @since 5.0.0
|
121 |
-
* @param array CSS classes
|
122 |
-
* @param int The post ID
|
123 |
-
* @return array The new CSS classes
|
124 |
-
*/
|
125 |
-
$classes = apply_filters(
|
126 |
-
'wpp_thumbnail_class_attribute',
|
127 |
-
$classes,
|
128 |
-
$post_object->id
|
129 |
-
);
|
130 |
-
|
131 |
-
/**
|
132 |
-
* Filters CSS classes assigned to the thumbnail
|
133 |
-
*
|
134 |
-
* @since 5.0.0
|
135 |
-
* @param string Original ALT attribute
|
136 |
-
* @param int The post ID
|
137 |
-
* @return string The new ALT attribute
|
138 |
-
*/
|
139 |
-
$alt = apply_filters(
|
140 |
-
'wpp_thumbnail_alt_attribute',
|
141 |
-
$this->get_alt_attribute($post_object->id, $source),
|
142 |
-
$post_object->id
|
143 |
-
);
|
144 |
-
|
145 |
-
return $this->render(
|
146 |
-
$cached,
|
147 |
-
$size,
|
148 |
-
is_array($classes) ? implode(' ', $classes) : 'wpp-thumbnail wpp_' . $source,
|
149 |
-
is_string($alt) ? $alt : ''
|
150 |
-
);
|
151 |
-
}
|
152 |
-
|
153 |
-
$thumb_url = null;
|
154 |
-
|
155 |
-
// Return image as-is, no need to create a new thumbnail
|
156 |
-
if (
|
157 |
-
( 'custom_field' == $source && ! $this->admin_options['tools']['thumbnail']['resize'] )
|
158 |
-
|| ( 'featured' == $source && 'predefined' == $build )
|
159 |
-
){
|
160 |
-
/**
|
161 |
-
* Filters CSS classes assigned to the thumbnail
|
162 |
-
*
|
163 |
-
* @since 5.0.0
|
164 |
-
* @param array CSS classes
|
165 |
-
* @param int The post ID
|
166 |
-
* @return array The new CSS classes
|
167 |
-
*/
|
168 |
-
$classes = apply_filters(
|
169 |
-
'wpp_thumbnail_class_attribute',
|
170 |
-
$classes,
|
171 |
-
$post_object->id
|
172 |
-
);
|
173 |
-
|
174 |
-
// Get custom field image URL
|
175 |
-
if ( 'custom_field' == $source && ! $this->admin_options['tools']['thumbnail']['resize'] ) {
|
176 |
-
$thumb_url = get_post_meta(
|
177 |
-
$post_object->id,
|
178 |
-
$this->admin_options['tools']['thumbnail']['field'],
|
179 |
-
true
|
180 |
-
);
|
181 |
-
|
182 |
-
if ( ! $thumb_url || ! $this->is_image_url($thumb_url) ) {
|
183 |
-
// Is this an attachment ID instead of an image URL?
|
184 |
-
if ( Helper::is_number($thumb_url) ) {
|
185 |
-
$thumb_url = wp_get_attachment_image_src($thumb_url, 'full');
|
186 |
-
$thumb_url = is_array($thumb_url) ? $thumb_url[0] : null;
|
187 |
-
} else {
|
188 |
-
$thumb_url = null;
|
189 |
-
}
|
190 |
-
}
|
191 |
-
|
192 |
-
if ( $thumb_url ) {
|
193 |
-
/**
|
194 |
-
* Filters CSS classes assigned to the thumbnail
|
195 |
-
*
|
196 |
-
* @since 5.0.0
|
197 |
-
* @param string Original ALT attribute
|
198 |
-
* @param int The post ID
|
199 |
-
* @return string The new ALT attribute
|
200 |
-
*/
|
201 |
-
$alt = apply_filters(
|
202 |
-
'wpp_thumbnail_alt_attribute',
|
203 |
-
'',
|
204 |
-
$post_object->id
|
205 |
-
);
|
206 |
-
}
|
207 |
-
}
|
208 |
-
// Get Post Thumbnail
|
209 |
-
else {
|
210 |
-
if (
|
211 |
-
current_theme_supports('post-thumbnails')
|
212 |
-
&& has_post_thumbnail($post_object->id)
|
213 |
-
) {
|
214 |
-
// Find corresponding image size
|
215 |
-
$stock_size = null;
|
216 |
-
$images_sizes = $this->get_sizes();
|
217 |
-
|
218 |
-
foreach ( $images_sizes as $name => $attr ) :
|
219 |
-
if (
|
220 |
-
$attr['width'] == $size[0]
|
221 |
-
&& $attr['height'] == $size[1]
|
222 |
-
&& $attr['crop'] == $crop
|
223 |
-
) {
|
224 |
-
$stock_size = $name;
|
225 |
-
break;
|
226 |
-
}
|
227 |
-
endforeach;
|
228 |
-
|
229 |
-
// Couldn't find a matching size so let's go with width/height combo instead
|
230 |
-
// (this should never happen but better safe than sorry!)
|
231 |
-
if ( null == $stock_size ) {
|
232 |
-
$stock_size = $size;
|
233 |
-
}
|
234 |
-
|
235 |
-
$featured_image = get_the_post_thumbnail(
|
236 |
-
$post_object->id,
|
237 |
-
$stock_size
|
238 |
-
);
|
239 |
-
|
240 |
-
if ( strpos($featured_image, 'class="') && is_array($classes) && ! empty($classes) )
|
241 |
-
$featured_image = str_replace('class="', 'class="'. esc_attr(implode(' ', $classes)) . ' ', $featured_image);
|
242 |
-
|
243 |
-
if ( $this->admin_options['tools']['thumbnail']['lazyload'] && false == strpos($featured_image, 'loading="lazy"') ) {
|
244 |
-
$featured_image = str_replace('src="', 'loading="lazy" src="', $featured_image);
|
245 |
-
}
|
246 |
-
|
247 |
-
return $featured_image;
|
248 |
-
}
|
249 |
-
}
|
250 |
-
}
|
251 |
-
// Build a new thumbnail and return it
|
252 |
-
else {
|
253 |
-
$file_path = null;
|
254 |
-
|
255 |
-
if ( 'custom_field' == $source && $this->admin_options['tools']['thumbnail']['resize'] ) {
|
256 |
-
$thumb_url = get_post_meta(
|
257 |
-
$post_object->id,
|
258 |
-
$this->admin_options['tools']['thumbnail']['field'],
|
259 |
-
true
|
260 |
-
);
|
261 |
-
|
262 |
-
if ( ! $thumb_url || ! $this->is_image_url($thumb_url) ) {
|
263 |
-
// Is this an attachment ID instead of an image URL?
|
264 |
-
// If so, try to fetch the image
|
265 |
-
if ( Helper::is_number($thumb_url) ) {
|
266 |
-
$thumb_url = wp_get_attachment_image_src($thumb_url, 'full');
|
267 |
-
$thumb_url = is_array($thumb_url) ? $thumb_url[0] : null;
|
268 |
-
} else {
|
269 |
-
$thumb_url = null;
|
270 |
-
}
|
271 |
-
}
|
272 |
-
|
273 |
-
if ( $thumb_url && $this->is_image_url($thumb_url) ) {
|
274 |
-
$file_path = $this->url_to_path($thumb_url, $post_object->id);
|
275 |
-
}
|
276 |
-
} else {
|
277 |
-
$file_meta = $this->get_file_meta($post_object->id, $source);
|
278 |
-
|
279 |
-
if ( is_array($file_meta) && isset($file_meta['path']) ) {
|
280 |
-
$alt = isset($file_meta['alt']) ? $file_meta['alt'] : '';
|
281 |
-
$file_path = $file_meta['path'];
|
282 |
-
}
|
283 |
-
}
|
284 |
-
|
285 |
-
if ( $file_path ) {
|
286 |
-
$extension = pathinfo($file_path, PATHINFO_EXTENSION);
|
287 |
-
$thumb_url = $this->resize(
|
288 |
-
$file_path,
|
289 |
-
$filename . '.' . $extension,
|
290 |
-
$size,
|
291 |
-
$crop
|
292 |
-
);
|
293 |
-
}
|
294 |
-
}
|
295 |
-
|
296 |
-
if ( ! $thumb_url ) {
|
297 |
-
$classes[] = 'wpp_def_no_src';
|
298 |
-
$thumb_url = $this->get_default_url($post_object->id);
|
299 |
-
}
|
300 |
-
|
301 |
-
return $this->render(
|
302 |
-
$thumb_url,
|
303 |
-
$size,
|
304 |
-
is_array($classes) ? implode(' ', $classes) : 'wpp-thumbnail wpp_' . $source,
|
305 |
-
is_string($alt) ? $alt : ''
|
306 |
-
);
|
307 |
-
}
|
308 |
-
|
309 |
-
/**
|
310 |
-
* Checks whether a given thumbnail exists.
|
311 |
-
*
|
312 |
-
* @since 5.0.0
|
313 |
-
* @access private
|
314 |
-
* @param string $filename
|
315 |
-
* @return string|bool Full URL to image
|
316 |
-
*/
|
317 |
-
private function exists($filename)
|
318 |
-
{
|
319 |
-
// Do we have thumbnail already?
|
320 |
-
$file = $this->resolve(trailingslashit($this->get_plugin_uploads_dir()['basedir']) . $filename);
|
321 |
-
|
322 |
-
if ( $file && is_file($file) ) {
|
323 |
-
$extension = pathinfo($file, PATHINFO_EXTENSION);
|
324 |
-
return trailingslashit($this->get_plugin_uploads_dir()['baseurl']) . $filename . '.' . $extension;
|
325 |
-
}
|
326 |
-
|
327 |
-
return false;
|
328 |
-
}
|
329 |
-
|
330 |
-
/**
|
331 |
-
* Resolves filename.
|
332 |
-
*
|
333 |
-
* @since 5.0.0
|
334 |
-
* @access private
|
335 |
-
* @author Ioan Chiriac
|
336 |
-
* @link https://stackoverflow.com/a/29468093/9131961
|
337 |
-
* @param string $name
|
338 |
-
* @return string|bool Resolved path, or false if not found
|
339 |
-
*/
|
340 |
-
private function resolve($name)
|
341 |
-
{
|
342 |
-
$info = pathinfo($name);
|
343 |
-
|
344 |
-
// File already contains an extension, return it
|
345 |
-
if ( isset($info['extension']) && ! empty($info['extension']) ) {
|
346 |
-
return $name;
|
347 |
-
}
|
348 |
-
|
349 |
-
$filename = $info['filename'];
|
350 |
-
$len = strlen($filename);
|
351 |
-
|
352 |
-
// open the folder
|
353 |
-
$dh = opendir($info['dirname']);
|
354 |
-
|
355 |
-
if ( ! $dh ) {
|
356 |
-
return false;
|
357 |
-
}
|
358 |
-
|
359 |
-
// scan each file in the folder
|
360 |
-
while ( ($file = readdir($dh)) !== false ) {
|
361 |
-
if ( strncmp($file, $filename, $len) === 0 ) {
|
362 |
-
if ( strlen($name) > $len ) {
|
363 |
-
// if name contains a directory part
|
364 |
-
$name = substr($name, 0, strlen($name) - $len) . $file;
|
365 |
-
} else {
|
366 |
-
// if the name is at the path root
|
367 |
-
$name = $file;
|
368 |
-
}
|
369 |
-
|
370 |
-
closedir($dh);
|
371 |
-
return $name;
|
372 |
-
}
|
373 |
-
}
|
374 |
-
|
375 |
-
// file not found
|
376 |
-
closedir($dh);
|
377 |
-
return false;
|
378 |
-
}
|
379 |
-
|
380 |
-
/**
|
381 |
-
* Retrieves local path to image.
|
382 |
-
*
|
383 |
-
* @since 5.0.0
|
384 |
-
* @access private
|
385 |
-
* @param string $url
|
386 |
-
* @param integer $post_ID
|
387 |
-
* @return string|boolean Path to image, or false if not found
|
388 |
-
*/
|
389 |
-
private function url_to_path($url, $post_ID = null)
|
390 |
-
{
|
391 |
-
if ( $this->is_image_url($url) ) {
|
392 |
-
$attachment_id = $this->get_attachment_id($url);
|
393 |
-
|
394 |
-
// Image is hosted locally
|
395 |
-
if ( $attachment_id ) {
|
396 |
-
return get_attached_file($attachment_id);
|
397 |
-
}
|
398 |
-
|
399 |
-
// Image hosted elsewhere?
|
400 |
-
if ( $post_ID && Helper::is_number($post_ID) )
|
401 |
-
return $this->fetch_external_image($post_ID, $url);
|
402 |
-
}
|
403 |
-
|
404 |
-
return false;
|
405 |
-
}
|
406 |
-
|
407 |
-
/**
|
408 |
-
* Gets image meta.
|
409 |
-
*
|
410 |
-
* @since 5.0.0
|
411 |
-
* @access private
|
412 |
-
* @param int $id Post ID
|
413 |
-
* @param string $source Image source
|
414 |
-
* @return array|bool
|
415 |
-
*/
|
416 |
-
private function get_file_meta($id, $source)
|
417 |
-
{
|
418 |
-
// get thumbnail path from the Featured Image
|
419 |
-
if ( "featured" == $source ) {
|
420 |
-
if ( $thumbnail_id = get_post_thumbnail_id($id) ) {
|
421 |
-
// image path
|
422 |
-
return [
|
423 |
-
'path' => get_attached_file($thumbnail_id),
|
424 |
-
'alt' => get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true)
|
425 |
-
];
|
426 |
-
}
|
427 |
-
}
|
428 |
-
// get thumbnail path from first image attachment
|
429 |
-
elseif ( "first_attachment" == $source ) {
|
430 |
-
$args = [
|
431 |
-
'numberposts' => 1,
|
432 |
-
'order' => 'ASC',
|
433 |
-
'post_parent' => $id,
|
434 |
-
'post_type' => 'attachment',
|
435 |
-
'post_mime_type' => 'image'
|
436 |
-
];
|
437 |
-
$post_attachments = get_children($args);
|
438 |
-
|
439 |
-
if ( ! empty($post_attachments) ) {
|
440 |
-
$first_img = array_shift($post_attachments);
|
441 |
-
|
442 |
-
return [
|
443 |
-
'path' => get_attached_file($first_img->ID),
|
444 |
-
'alt' => get_post_meta($first_img->ID, '_wp_attachment_image_alt', true)
|
445 |
-
];
|
446 |
-
}
|
447 |
-
}
|
448 |
-
// get thumbnail path from post content
|
449 |
-
elseif ( "first_image" == $source ) {
|
450 |
-
/** @var wpdb $wpdb */
|
451 |
-
global $wpdb;
|
452 |
-
|
453 |
-
if ( $content = $wpdb->get_var("SELECT post_content FROM {$wpdb->posts} WHERE ID = {$id};") ) {
|
454 |
-
// at least one image has been found
|
455 |
-
if ( preg_match('/<img[^>]+>/i', $content, $img) ) {
|
456 |
-
// get img src attribute from the first image found
|
457 |
-
preg_match('/(src)="([^"]*)"/i', $img[0], $src_attr);
|
458 |
-
|
459 |
-
if ( isset($src_attr[2]) && ! empty($src_attr[2]) ) {
|
460 |
-
// get img alt attribute from the first image found
|
461 |
-
$alt = '';
|
462 |
-
preg_match('/(alt)="([^"]*)"/i', $img[0], $alt_attr);
|
463 |
-
|
464 |
-
if ( isset($alt_attr[2]) && !empty($alt_attr[2]) ) {
|
465 |
-
$alt = $alt_attr[2];
|
466 |
-
}
|
467 |
-
|
468 |
-
// image from Media Library
|
469 |
-
if ( $attachment_id = $this->get_attachment_id($src_attr[2]) ) {
|
470 |
-
return [
|
471 |
-
'path' => get_attached_file($attachment_id),
|
472 |
-
'alt' => $alt
|
473 |
-
];
|
474 |
-
} // external image?
|
475 |
-
else {
|
476 |
-
return [
|
477 |
-
'path' => $this->fetch_external_image($id, $src_attr[2]),
|
478 |
-
'alt' => $alt
|
479 |
-
];
|
480 |
-
}
|
481 |
-
}
|
482 |
-
}
|
483 |
-
}
|
484 |
-
}
|
485 |
-
|
486 |
-
return false;
|
487 |
-
}
|
488 |
-
|
489 |
-
/**
|
490 |
-
* Gets image ALT attribute.
|
491 |
-
*
|
492 |
-
* @since 5.0.0
|
493 |
-
* @access private
|
494 |
-
* @param int $id Post ID
|
495 |
-
* @param string $source Image source
|
496 |
-
* @return string
|
497 |
-
*/
|
498 |
-
private function get_alt_attribute($id, $source)
|
499 |
-
{
|
500 |
-
$alt = '';
|
501 |
-
|
502 |
-
// get thumbnail path from the Featured Image
|
503 |
-
if ( "featured" == $source ) {
|
504 |
-
if ( $thumbnail_id = get_post_thumbnail_id($id) ) {
|
505 |
-
// image path
|
506 |
-
$alt = get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true);
|
507 |
-
}
|
508 |
-
}
|
509 |
-
// get thumbnail path from first image attachment
|
510 |
-
elseif ( "first_attachment" == $source ) {
|
511 |
-
$args = [
|
512 |
-
'numberposts' => 1,
|
513 |
-
'order' => 'ASC',
|
514 |
-
'post_parent' => $id,
|
515 |
-
'post_type' => 'attachment',
|
516 |
-
'post_mime_type' => 'image'
|
517 |
-
];
|
518 |
-
$post_attachments = get_children($args);
|
519 |
-
|
520 |
-
if ( ! empty($post_attachments) ) {
|
521 |
-
$first_img = array_shift($post_attachments);
|
522 |
-
$alt = get_post_meta($first_img->ID, '_wp_attachment_image_alt', true);
|
523 |
-
}
|
524 |
-
}
|
525 |
-
// get thumbnail path from post content
|
526 |
-
elseif ( "first_image" == $source ) {
|
527 |
-
/** @var wpdb $wpdb */
|
528 |
-
global $wpdb;
|
529 |
-
|
530 |
-
if ( $content = $wpdb->get_var("SELECT post_content FROM {$wpdb->posts} WHERE ID = {$id};") ) {
|
531 |
-
// at least one image has been found
|
532 |
-
if ( preg_match('/<img[^>]+>/i', $content, $img) ) {
|
533 |
-
// get img alt attribute from the first image found
|
534 |
-
preg_match('/(alt)="([^"]*)"/i', $img[0], $alt_attr);
|
535 |
-
|
536 |
-
if ( isset($alt_attr[2]) && !empty($alt_attr[2]) ) {
|
537 |
-
$alt = $alt_attr[2];
|
538 |
-
}
|
539 |
-
}
|
540 |
-
}
|
541 |
-
}
|
542 |
-
|
543 |
-
return $alt;
|
544 |
-
}
|
545 |
-
|
546 |
-
/**
|
547 |
-
* Get the Attachment ID for a given image URL.
|
548 |
-
*
|
549 |
-
* @since 3.0.0
|
550 |
-
* @access private
|
551 |
-
* @author Frankie Jarrett
|
552 |
-
* @link http://frankiejarrett.com/get-an-attachment-id-by-url-in-wordpress/
|
553 |
-
* @param string $url
|
554 |
-
* @return int|null
|
555 |
-
*/
|
556 |
-
private function get_attachment_id($url)
|
557 |
-
{
|
558 |
-
$url = Helper::add_scheme(
|
559 |
-
$url,
|
560 |
-
is_ssl() ? 'https://' : 'http://'
|
561 |
-
);
|
562 |
-
|
563 |
-
// Split the $url into two parts with the wp-content directory as the separator.
|
564 |
-
$parse_url = explode(parse_url(WP_CONTENT_URL, PHP_URL_PATH), $url);
|
565 |
-
|
566 |
-
// Get the host of the current site and the host of the $url, ignoring www.
|
567 |
-
$this_host = str_ireplace('www.', '', parse_url(home_url(), PHP_URL_HOST));
|
568 |
-
$file_host = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));
|
569 |
-
|
570 |
-
// Return nothing if there aren't any $url parts or if the current host and $url host do not match.
|
571 |
-
if (
|
572 |
-
! isset($parse_url[1])
|
573 |
-
|| empty($parse_url[1])
|
574 |
-
|| ($this_host != $file_host)
|
575 |
-
) {
|
576 |
-
return false;
|
577 |
-
}
|
578 |
-
|
579 |
-
// Now we're going to quickly search the DB for any attachment GUID with a partial path match.
|
580 |
-
// Example: /uploads/2013/05/test-image.jpg
|
581 |
-
global $wpdb;
|
582 |
-
|
583 |
-
if ( ! $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parse_url[1])) ) {
|
584 |
-
// Maybe it's a resized image, so try to get the full one
|
585 |
-
$parse_url[1] = preg_replace('/-[0-9]{1,4}x[0-9]{1,4}\.(jpg|jpeg|png|gif|bmp)$/i', '.$1', $parse_url[1]);
|
586 |
-
$attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parse_url[1]));
|
587 |
-
}
|
588 |
-
|
589 |
-
// Returns null if no attachment is found.
|
590 |
-
return isset($attachment[0]) ? $attachment[0] : NULL;
|
591 |
-
}
|
592 |
-
|
593 |
-
/**
|
594 |
-
* Fetchs external images.
|
595 |
-
*
|
596 |
-
* @since 2.3.3
|
597 |
-
* @access private
|
598 |
-
* @param int $id Post ID.
|
599 |
-
* @param string $url Image url.
|
600 |
-
* @return string|bool Image path, or false on failure.
|
601 |
-
*/
|
602 |
-
private function fetch_external_image($id, $url)
|
603 |
-
{
|
604 |
-
$full_image_path = trailingslashit($this->get_plugin_uploads_dir()['basedir']) . "{$id}_" . sanitize_file_name(rawurldecode(wp_basename($url)));
|
605 |
-
|
606 |
-
// if the file exists already, return URL and path
|
607 |
-
if ( file_exists($full_image_path) )
|
608 |
-
return $full_image_path;
|
609 |
-
|
610 |
-
$url = Helper::add_scheme(
|
611 |
-
$url,
|
612 |
-
is_ssl() ? 'https://' : 'http://'
|
613 |
-
);
|
614 |
-
|
615 |
-
$accepted_status_codes = [200, 301, 302];
|
616 |
-
$response = wp_remote_head($url, ['timeout' => 5, 'sslverify' => false]);
|
617 |
-
|
618 |
-
if (
|
619 |
-
! is_wp_error($response)
|
620 |
-
&& in_array(wp_remote_retrieve_response_code($response), $accepted_status_codes)
|
621 |
-
) {
|
622 |
-
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
623 |
-
|
624 |
-
$url = str_replace('https://', 'http://', $url);
|
625 |
-
$tmp = download_url($url);
|
626 |
-
|
627 |
-
// File was downloaded successfully
|
628 |
-
if ( ! is_wp_error($tmp) ) {
|
629 |
-
// Determine image type
|
630 |
-
if ( function_exists('exif_imagetype') ) {
|
631 |
-
$image_type = exif_imagetype($tmp);
|
632 |
-
} else {
|
633 |
-
$image_type = getimagesize($tmp);
|
634 |
-
$image_type = ( isset($image_type[2]) ) ? $image_type[2] : NULL;
|
635 |
-
}
|
636 |
-
|
637 |
-
// Valid image, save it
|
638 |
-
if ( in_array($image_type, [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG]) ) {
|
639 |
-
// move file to Uploads
|
640 |
-
if ( @rename($tmp, $full_image_path) ) {
|
641 |
-
// borrowed from WP - set correct file permissions
|
642 |
-
$stat = stat(dirname($full_image_path));
|
643 |
-
$perms = $stat['mode'] & 0000644;
|
644 |
-
@chmod($full_image_path, $perms);
|
645 |
-
|
646 |
-
return $full_image_path;
|
647 |
-
}
|
648 |
-
}
|
649 |
-
|
650 |
-
// Invalid file, remove it
|
651 |
-
@unlink($tmp);
|
652 |
-
}
|
653 |
-
}
|
654 |
-
|
655 |
-
return false;
|
656 |
-
}
|
657 |
-
|
658 |
-
/**
|
659 |
-
* Resizes image.
|
660 |
-
*
|
661 |
-
* @since 3.0.0
|
662 |
-
* @access private
|
663 |
-
* @param string $path Image path
|
664 |
-
* @param string $filename Image filename
|
665 |
-
* @param array $size Image size
|
666 |
-
* @param bool $crop Whether to crop the image or not
|
667 |
-
* @return string|bool Image URL on success, false on error
|
668 |
-
*/
|
669 |
-
private function resize($path, $filename, $size, $crop = true)
|
670 |
-
{
|
671 |
-
$image = wp_get_image_editor($path);
|
672 |
-
|
673 |
-
// valid image, create thumbnail
|
674 |
-
if ( ! is_wp_error($image) ) {
|
675 |
-
/**
|
676 |
-
* Hook to change the image compression quality of WPP's thumbnails.
|
677 |
-
* @since 4.2.1
|
678 |
-
*/
|
679 |
-
$quality = apply_filters('wpp_thumbnail_compression_quality', null);
|
680 |
-
|
681 |
-
if ( ! ctype_digit($quality) )
|
682 |
-
$quality = null; // Fallback to core's default
|
683 |
-
|
684 |
-
$image->set_quality($quality);
|
685 |
-
|
686 |
-
$image->resize($size[0], $size[1], $crop);
|
687 |
-
$new_img = $image->save(trailingslashit($this->get_plugin_uploads_dir()['basedir']) . $filename);
|
688 |
-
|
689 |
-
if ( ! is_wp_error($new_img) )
|
690 |
-
return trailingslashit($this->get_plugin_uploads_dir()['baseurl']) . $filename;
|
691 |
-
}
|
692 |
-
|
693 |
-
return false;
|
694 |
-
}
|
695 |
-
|
696 |
-
/**
|
697 |
-
* Render image tag.
|
698 |
-
*
|
699 |
-
* @since 3.0.0
|
700 |
-
* @access public
|
701 |
-
* @param string $src Image URL
|
702 |
-
* @param array $dimension Image's width and height
|
703 |
-
* @param string $class CSS class
|
704 |
-
* @param object $alt Alternative text
|
705 |
-
* @param string $error Error, if the image could not be created
|
706 |
-
* @return string
|
707 |
-
*/
|
708 |
-
public function render($src, $size, $class, $alt = '', $error = null)
|
709 |
-
{
|
710 |
-
$img_tag = '';
|
711 |
-
|
712 |
-
if ( $error ) {
|
713 |
-
$img_tag = '<!-- ' . $error . ' --> ';
|
714 |
-
}
|
715 |
-
|
716 |
-
$src = 'src="' . esc_url(is_ssl() ? str_ireplace("http://", "https://", $src) : $src) . '"';
|
717 |
-
$lazyload = ( $this->admin_options['tools']['thumbnail']['lazyload'] ) ? ' loading="lazy"' : '';
|
718 |
-
|
719 |
-
$img_tag .= '<img ' . $src . ' width="' . $size[0] . '" height="' . $size[1] . '" alt="' . esc_attr($alt) . '" class="' . esc_attr($class) . '"' . $lazyload . ' />';
|
720 |
-
|
721 |
-
return apply_filters('wpp_render_image', $img_tag);
|
722 |
-
}
|
723 |
-
|
724 |
-
/**
|
725 |
-
* Gets list of available thumbnails sizes
|
726 |
-
*
|
727 |
-
* @since 3.2.0
|
728 |
-
* @link http://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes
|
729 |
-
* @param string $size
|
730 |
-
* @return array|bool
|
731 |
-
*/
|
732 |
-
public function get_sizes($size = '')
|
733 |
-
{
|
734 |
-
if ( ! is_array($this->available_sizes) || empty($this->available_sizes) ) {
|
735 |
-
global $_wp_additional_image_sizes;
|
736 |
-
|
737 |
-
$this->available_sizes = [];
|
738 |
-
$get_intermediate_image_sizes = get_intermediate_image_sizes();
|
739 |
-
|
740 |
-
// Create the full array with sizes and crop info
|
741 |
-
foreach( $get_intermediate_image_sizes as $_size ) {
|
742 |
-
if ( in_array($_size, ['thumbnail', 'medium', 'large']) ) {
|
743 |
-
$this->available_sizes[$_size]['width'] = get_option($_size . '_size_w');
|
744 |
-
$this->available_sizes[$_size]['height'] = get_option($_size . '_size_h');
|
745 |
-
$this->available_sizes[$_size]['crop'] = (bool) get_option($_size . '_crop');
|
746 |
-
} elseif ( isset($_wp_additional_image_sizes[$_size]) ) {
|
747 |
-
$this->available_sizes[$_size] = [
|
748 |
-
'width' => $_wp_additional_image_sizes[$_size]['width'],
|
749 |
-
'height' => $_wp_additional_image_sizes[$_size]['height'],
|
750 |
-
'crop' => $_wp_additional_image_sizes[$_size]['crop']
|
751 |
-
];
|
752 |
-
}
|
753 |
-
}
|
754 |
-
}
|
755 |
-
|
756 |
-
// Get only 1 size if found
|
757 |
-
if ( $size ) {
|
758 |
-
if ( isset($this->available_sizes[$size]) ) {
|
759 |
-
return $this->available_sizes[$size];
|
760 |
-
}
|
761 |
-
return false;
|
762 |
-
}
|
763 |
-
|
764 |
-
return $this->available_sizes;
|
765 |
-
}
|
766 |
-
|
767 |
-
/**
|
768 |
-
* Returns the URL of the default thumbnail image.
|
769 |
-
*
|
770 |
-
* @since 5.0.0
|
771 |
-
* @param int|null
|
772 |
-
* @return string
|
773 |
-
*/
|
774 |
-
public function get_default_url($post_ID = null)
|
775 |
-
{
|
776 |
-
if ( has_filter('wpp_default_thumbnail_url') ) {
|
777 |
-
$default_thumbnail_url = apply_filters('wpp_default_thumbnail_url', $this->default_thumbnail, $post_ID);
|
778 |
-
|
779 |
-
if ( $default_thumbnail_url != $this->default_thumbnail && $this->is_image_url($default_thumbnail_url) )
|
780 |
-
return $default_thumbnail_url;
|
781 |
-
}
|
782 |
-
|
783 |
-
return $this->default_thumbnail;
|
784 |
-
}
|
785 |
-
|
786 |
-
/**
|
787 |
-
* Checks whether an URL points to an actual image.
|
788 |
-
*
|
789 |
-
* @since 5.0.0
|
790 |
-
* @access private
|
791 |
-
* @param string
|
792 |
-
* @return array|bool
|
793 |
-
*/
|
794 |
-
private function is_image_url($url)
|
795 |
-
{
|
796 |
-
if ( ! filter_var($url, FILTER_VALIDATE_URL) )
|
797 |
-
return false;
|
798 |
-
|
799 |
-
// sanitize URL, just in case
|
800 |
-
$image_url = esc_url($url);
|
801 |
-
// remove querystring
|
802 |
-
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $image_url, $matches);
|
803 |
-
|
804 |
-
return ( is_array($matches) && ! empty($matches) ) ? $matches : false;
|
805 |
-
}
|
806 |
-
}
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* This class builds/retrieves the thumbnail image of each popular posts.
|
4 |
+
*
|
5 |
+
*
|
6 |
+
* @package WordPressPopularPosts
|
7 |
+
* @author Hector Cabrera <me@cabrerahector.com>
|
8 |
+
*/
|
9 |
+
|
10 |
+
namespace WordPressPopularPosts;
|
11 |
+
|
12 |
+
class Image {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Default thumbnail.
|
16 |
+
*
|
17 |
+
* @since 2.2.0
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
private $default_thumbnail = '';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Plugin uploads directory.
|
24 |
+
*
|
25 |
+
* @since 3.0.4
|
26 |
+
* @var array
|
27 |
+
*/
|
28 |
+
private $uploads_dir = [];
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Admin settings.
|
32 |
+
*
|
33 |
+
* @since 5.0.0
|
34 |
+
* @var array
|
35 |
+
*/
|
36 |
+
private $admin_options = [];
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Available image sizes.
|
40 |
+
*
|
41 |
+
* @since 5.0.0
|
42 |
+
* @var array
|
43 |
+
*/
|
44 |
+
private $available_sizes = [];
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Construct.
|
48 |
+
*
|
49 |
+
* @since 4.0.0
|
50 |
+
* @param array $admin_options
|
51 |
+
*/
|
52 |
+
public function __construct(array $admin_options)
|
53 |
+
{
|
54 |
+
$this->admin_options = $admin_options;
|
55 |
+
|
56 |
+
// Set default thumbnail
|
57 |
+
$this->default_thumbnail = plugins_url() . "/wordpress-popular-posts/assets/images/no_thumb.jpg";
|
58 |
+
|
59 |
+
if ( $this->is_image_url($this->admin_options['tools']['thumbnail']['default']) )
|
60 |
+
$this->default_thumbnail = $this->admin_options['tools']['thumbnail']['default'];
|
61 |
+
|
62 |
+
// Set uploads folder
|
63 |
+
$wp_upload_dir = wp_get_upload_dir();
|
64 |
+
$this->uploads_dir['basedir'] = $wp_upload_dir['basedir'] . "/" . 'wordpress-popular-posts';
|
65 |
+
$this->uploads_dir['baseurl'] = $wp_upload_dir['baseurl'] . "/" . 'wordpress-popular-posts';
|
66 |
+
|
67 |
+
if ( ! is_dir($this->uploads_dir['basedir']) ) {
|
68 |
+
// Couldn't create the folder, store thumbnails in Uploads
|
69 |
+
if ( ! wp_mkdir_p($this->uploads_dir['basedir']) ) {
|
70 |
+
$this->uploads_dir['basedir'] = $wp_upload_dir['basedir'];
|
71 |
+
$this->uploads_dir['baseurl'] = $wp_upload_dir['baseurl'];
|
72 |
+
}
|
73 |
+
}
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Get WPP's uploads folder.
|
78 |
+
*
|
79 |
+
* @since 4.0.0
|
80 |
+
* @access public
|
81 |
+
* @return array|bool
|
82 |
+
*/
|
83 |
+
public function get_plugin_uploads_dir()
|
84 |
+
{
|
85 |
+
if ( is_array($this->uploads_dir) && ! empty($this->uploads_dir) )
|
86 |
+
return $this->uploads_dir;
|
87 |
+
return false;
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Returns an image.
|
92 |
+
*
|
93 |
+
* @since 5.0.0
|
94 |
+
* @param \stdClass $post_object Post object
|
95 |
+
* @param array $size Image size (width & height)
|
96 |
+
* @param string $source Image source
|
97 |
+
* @param bool $crop Whether to crop the image or not
|
98 |
+
* @param string $build Whether to build the image or get an existing one
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function get($post_object, $size, $source, $crop = true, $build = 'manual')
|
102 |
+
{
|
103 |
+
// Bail, $post_object is not an actual object
|
104 |
+
if ( false === $post_object instanceof \stdClass || ! isset($post_object->id) ) {
|
105 |
+
return '';
|
106 |
+
}
|
107 |
+
|
108 |
+
$alt = '';
|
109 |
+
$classes = ['wpp-thumbnail', 'wpp_' . $source];
|
110 |
+
$filename = $post_object->id . '-' . $source . '-' . $size[0] . 'x' . $size[1];
|
111 |
+
$cached = $this->exists($filename);
|
112 |
+
|
113 |
+
// We have a thumbnail already, return it
|
114 |
+
if ( $cached ) {
|
115 |
+
$classes[] = 'wpp_cached_thumb';
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Filters CSS classes assigned to the thumbnail
|
119 |
+
*
|
120 |
+
* @since 5.0.0
|
121 |
+
* @param array CSS classes
|
122 |
+
* @param int The post ID
|
123 |
+
* @return array The new CSS classes
|
124 |
+
*/
|
125 |
+
$classes = apply_filters(
|
126 |
+
'wpp_thumbnail_class_attribute',
|
127 |
+
$classes,
|
128 |
+
$post_object->id
|
129 |
+
);
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Filters CSS classes assigned to the thumbnail
|
133 |
+
*
|
134 |
+
* @since 5.0.0
|
135 |
+
* @param string Original ALT attribute
|
136 |
+
* @param int The post ID
|
137 |
+
* @return string The new ALT attribute
|
138 |
+
*/
|
139 |
+
$alt = apply_filters(
|
140 |
+
'wpp_thumbnail_alt_attribute',
|
141 |
+
$this->get_alt_attribute($post_object->id, $source),
|
142 |
+
$post_object->id
|
143 |
+
);
|
144 |
+
|
145 |
+
return $this->render(
|
146 |
+
$cached,
|
147 |
+
$size,
|
148 |
+
is_array($classes) ? implode(' ', $classes) : 'wpp-thumbnail wpp_' . $source,
|
149 |
+
is_string($alt) ? $alt : ''
|
150 |
+
);
|
151 |
+
}
|
152 |
+
|
153 |
+
$thumb_url = null;
|
154 |
+
|
155 |
+
// Return image as-is, no need to create a new thumbnail
|
156 |
+
if (
|
157 |
+
( 'custom_field' == $source && ! $this->admin_options['tools']['thumbnail']['resize'] )
|
158 |
+
|| ( 'featured' == $source && 'predefined' == $build )
|
159 |
+
){
|
160 |
+
/**
|
161 |
+
* Filters CSS classes assigned to the thumbnail
|
162 |
+
*
|
163 |
+
* @since 5.0.0
|
164 |
+
* @param array CSS classes
|
165 |
+
* @param int The post ID
|
166 |
+
* @return array The new CSS classes
|
167 |
+
*/
|
168 |
+
$classes = apply_filters(
|
169 |
+
'wpp_thumbnail_class_attribute',
|
170 |
+
$classes,
|
171 |
+
$post_object->id
|
172 |
+
);
|
173 |
+
|
174 |
+
// Get custom field image URL
|
175 |
+
if ( 'custom_field' == $source && ! $this->admin_options['tools']['thumbnail']['resize'] ) {
|
176 |
+
$thumb_url = get_post_meta(
|
177 |
+
$post_object->id,
|
178 |
+
$this->admin_options['tools']['thumbnail']['field'],
|
179 |
+
true
|
180 |
+
);
|
181 |
+
|
182 |
+
if ( ! $thumb_url || ! $this->is_image_url($thumb_url) ) {
|
183 |
+
// Is this an attachment ID instead of an image URL?
|
184 |
+
if ( Helper::is_number($thumb_url) ) {
|
185 |
+
$thumb_url = wp_get_attachment_image_src($thumb_url, 'full');
|
186 |
+
$thumb_url = is_array($thumb_url) ? $thumb_url[0] : null;
|
187 |
+
} else {
|
188 |
+
$thumb_url = null;
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
if ( $thumb_url ) {
|
193 |
+
/**
|
194 |
+
* Filters CSS classes assigned to the thumbnail
|
195 |
+
*
|
196 |
+
* @since 5.0.0
|
197 |
+
* @param string Original ALT attribute
|
198 |
+
* @param int The post ID
|
199 |
+
* @return string The new ALT attribute
|
200 |
+
*/
|
201 |
+
$alt = apply_filters(
|
202 |
+
'wpp_thumbnail_alt_attribute',
|
203 |
+
'',
|
204 |
+
$post_object->id
|
205 |
+
);
|
206 |
+
}
|
207 |
+
}
|
208 |
+
// Get Post Thumbnail
|
209 |
+
else {
|
210 |
+
if (
|
211 |
+
current_theme_supports('post-thumbnails')
|
212 |
+
&& has_post_thumbnail($post_object->id)
|
213 |
+
) {
|
214 |
+
// Find corresponding image size
|
215 |
+
$stock_size = null;
|
216 |
+
$images_sizes = $this->get_sizes();
|
217 |
+
|
218 |
+
foreach ( $images_sizes as $name => $attr ) :
|
219 |
+
if (
|
220 |
+
$attr['width'] == $size[0]
|
221 |
+
&& $attr['height'] == $size[1]
|
222 |
+
&& $attr['crop'] == $crop
|
223 |
+
) {
|
224 |
+
$stock_size = $name;
|
225 |
+
break;
|
226 |
+
}
|
227 |
+
endforeach;
|
228 |
+
|
229 |
+
// Couldn't find a matching size so let's go with width/height combo instead
|
230 |
+
// (this should never happen but better safe than sorry!)
|
231 |
+
if ( null == $stock_size ) {
|
232 |
+
$stock_size = $size;
|
233 |
+
}
|
234 |
+
|
235 |
+
$featured_image = get_the_post_thumbnail(
|
236 |
+
$post_object->id,
|
237 |
+
$stock_size
|
238 |
+
);
|
239 |
+
|
240 |
+
if ( strpos($featured_image, 'class="') && is_array($classes) && ! empty($classes) )
|
241 |
+
$featured_image = str_replace('class="', 'class="'. esc_attr(implode(' ', $classes)) . ' ', $featured_image);
|
242 |
+
|
243 |
+
if ( $this->admin_options['tools']['thumbnail']['lazyload'] && false == strpos($featured_image, 'loading="lazy"') ) {
|
244 |
+
$featured_image = str_replace('src="', 'loading="lazy" src="', $featured_image);
|
245 |
+
}
|
246 |
+
|
247 |
+
return $featured_image;
|
248 |
+
}
|
249 |
+
}
|
250 |
+
}
|
251 |
+
// Build a new thumbnail and return it
|
252 |
+
else {
|
253 |
+
$file_path = null;
|
254 |
+
|
255 |
+
if ( 'custom_field' == $source && $this->admin_options['tools']['thumbnail']['resize'] ) {
|
256 |
+
$thumb_url = get_post_meta(
|
257 |
+
$post_object->id,
|
258 |
+
$this->admin_options['tools']['thumbnail']['field'],
|
259 |
+
true
|
260 |
+
);
|
261 |
+
|
262 |
+
if ( ! $thumb_url || ! $this->is_image_url($thumb_url) ) {
|
263 |
+
// Is this an attachment ID instead of an image URL?
|
264 |
+
// If so, try to fetch the image
|
265 |
+
if ( Helper::is_number($thumb_url) ) {
|
266 |
+
$thumb_url = wp_get_attachment_image_src($thumb_url, 'full');
|
267 |
+
$thumb_url = is_array($thumb_url) ? $thumb_url[0] : null;
|
268 |
+
} else {
|
269 |
+
$thumb_url = null;
|
270 |
+
}
|
271 |
+
}
|
272 |
+
|
273 |
+
if ( $thumb_url && $this->is_image_url($thumb_url) ) {
|
274 |
+
$file_path = $this->url_to_path($thumb_url, $post_object->id);
|
275 |
+
}
|
276 |
+
} else {
|
277 |
+
$file_meta = $this->get_file_meta($post_object->id, $source);
|
278 |
+
|
279 |
+
if ( is_array($file_meta) && isset($file_meta['path']) ) {
|
280 |
+
$alt = isset($file_meta['alt']) ? $file_meta['alt'] : '';
|
281 |
+
$file_path = $file_meta['path'];
|
282 |
+
}
|
283 |
+
}
|
284 |
+
|
285 |
+
if ( $file_path ) {
|
286 |
+
$extension = pathinfo($file_path, PATHINFO_EXTENSION);
|
287 |
+
$thumb_url = $this->resize(
|
288 |
+
$file_path,
|
289 |
+
$filename . '.' . $extension,
|
290 |
+
$size,
|
291 |
+
$crop
|
292 |
+
);
|
293 |
+
}
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( ! $thumb_url ) {
|
297 |
+
$classes[] = 'wpp_def_no_src';
|
298 |
+
$thumb_url = $this->get_default_url($post_object->id);
|
299 |
+
}
|
300 |
+
|
301 |
+
return $this->render(
|
302 |
+
$thumb_url,
|
303 |
+
$size,
|
304 |
+
is_array($classes) ? implode(' ', $classes) : 'wpp-thumbnail wpp_' . $source,
|
305 |
+
is_string($alt) ? $alt : ''
|
306 |
+
);
|
307 |
+
}
|
308 |
+
|
309 |
+
/**
|
310 |
+
* Checks whether a given thumbnail exists.
|
311 |
+
*
|
312 |
+
* @since 5.0.0
|
313 |
+
* @access private
|
314 |
+
* @param string $filename
|
315 |
+
* @return string|bool Full URL to image
|
316 |
+
*/
|
317 |
+
private function exists($filename)
|
318 |
+
{
|
319 |
+
// Do we have thumbnail already?
|
320 |
+
$file = $this->resolve(trailingslashit($this->get_plugin_uploads_dir()['basedir']) . $filename);
|
321 |
+
|
322 |
+
if ( $file && is_file($file) ) {
|
323 |
+
$extension = pathinfo($file, PATHINFO_EXTENSION);
|
324 |
+
return trailingslashit($this->get_plugin_uploads_dir()['baseurl']) . $filename . '.' . $extension;
|
325 |
+
}
|
326 |
+
|
327 |
+
return false;
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Resolves filename.
|
332 |
+
*
|
333 |
+
* @since 5.0.0
|
334 |
+
* @access private
|
335 |
+
* @author Ioan Chiriac
|
336 |
+
* @link https://stackoverflow.com/a/29468093/9131961
|
337 |
+
* @param string $name
|
338 |
+
* @return string|bool Resolved path, or false if not found
|
339 |
+
*/
|
340 |
+
private function resolve($name)
|
341 |
+
{
|
342 |
+
$info = pathinfo($name);
|
343 |
+
|
344 |
+
// File already contains an extension, return it
|
345 |
+
if ( isset($info['extension']) && ! empty($info['extension']) ) {
|
346 |
+
return $name;
|
347 |
+
}
|
348 |
+
|
349 |
+
$filename = $info['filename'];
|
350 |
+
$len = strlen($filename);
|
351 |
+
|
352 |
+
// open the folder
|
353 |
+
$dh = opendir($info['dirname']);
|
354 |
+
|
355 |
+
if ( ! $dh ) {
|
356 |
+
return false;
|
357 |
+
}
|
358 |
+
|
359 |
+
// scan each file in the folder
|
360 |
+
while ( ($file = readdir($dh)) !== false ) {
|
361 |
+
if ( strncmp($file, $filename, $len) === 0 ) {
|
362 |
+
if ( strlen($name) > $len ) {
|
363 |
+
// if name contains a directory part
|
364 |
+
$name = substr($name, 0, strlen($name) - $len) . $file;
|
365 |
+
} else {
|
366 |
+
// if the name is at the path root
|
367 |
+
$name = $file;
|
368 |
+
}
|
369 |
+
|
370 |
+
closedir($dh);
|
371 |
+
return $name;
|
372 |
+
}
|
373 |
+
}
|
374 |
+
|
375 |
+
// file not found
|
376 |
+
closedir($dh);
|
377 |
+
return false;
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Retrieves local path to image.
|
382 |
+
*
|
383 |
+
* @since 5.0.0
|
384 |
+
* @access private
|
385 |
+
* @param string $url
|
386 |
+
* @param integer $post_ID
|
387 |
+
* @return string|boolean Path to image, or false if not found
|
388 |
+
*/
|
389 |
+
private function url_to_path($url, $post_ID = null)
|
390 |
+
{
|
391 |
+
if ( $this->is_image_url($url) ) {
|
392 |
+
$attachment_id = $this->get_attachment_id($url);
|
393 |
+
|
394 |
+
// Image is hosted locally
|
395 |
+
if ( $attachment_id ) {
|
396 |
+
return get_attached_file($attachment_id);
|
397 |
+
}
|
398 |
+
|
399 |
+
// Image hosted elsewhere?
|
400 |
+
if ( $post_ID && Helper::is_number($post_ID) )
|
401 |
+
return $this->fetch_external_image($post_ID, $url);
|
402 |
+
}
|
403 |
+
|
404 |
+
return false;
|
405 |
+
}
|
406 |
+
|
407 |
+
/**
|
408 |
+
* Gets image meta.
|
409 |
+
*
|
410 |
+
* @since 5.0.0
|
411 |
+
* @access private
|
412 |
+
* @param int $id Post ID
|
413 |
+
* @param string $source Image source
|
414 |
+
* @return array|bool
|
415 |
+
*/
|
416 |
+
private function get_file_meta($id, $source)
|
417 |
+
{
|
418 |
+
// get thumbnail path from the Featured Image
|
419 |
+
if ( "featured" == $source ) {
|
420 |
+
if ( $thumbnail_id = get_post_thumbnail_id($id) ) {
|
421 |
+
// image path
|
422 |
+
return [
|
423 |
+
'path' => get_attached_file($thumbnail_id),
|
424 |
+
'alt' => get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true)
|
425 |
+
];
|
426 |
+
}
|
427 |
+
}
|
428 |
+
// get thumbnail path from first image attachment
|
429 |
+
elseif ( "first_attachment" == $source ) {
|
430 |
+
$args = [
|
431 |
+
'numberposts' => 1,
|
432 |
+
'order' => 'ASC',
|
433 |
+
'post_parent' => $id,
|
434 |
+
'post_type' => 'attachment',
|
435 |
+
'post_mime_type' => 'image'
|
436 |
+
];
|
437 |
+
$post_attachments = get_children($args);
|
438 |
+
|
439 |
+
if ( ! empty($post_attachments) ) {
|
440 |
+
$first_img = array_shift($post_attachments);
|
441 |
+
|
442 |
+
return [
|
443 |
+
'path' => get_attached_file($first_img->ID),
|
444 |
+
'alt' => get_post_meta($first_img->ID, '_wp_attachment_image_alt', true)
|
445 |
+
];
|
446 |
+
}
|
447 |
+
}
|
448 |
+
// get thumbnail path from post content
|
449 |
+
elseif ( "first_image" == $source ) {
|
450 |
+
/** @var wpdb $wpdb */
|
451 |
+
global $wpdb;
|
452 |
+
|
453 |
+
if ( $content = $wpdb->get_var("SELECT post_content FROM {$wpdb->posts} WHERE ID = {$id};") ) {
|
454 |
+
// at least one image has been found
|
455 |
+
if ( preg_match('/<img[^>]+>/i', $content, $img) ) {
|
456 |
+
// get img src attribute from the first image found
|
457 |
+
preg_match('/(src)="([^"]*)"/i', $img[0], $src_attr);
|
458 |
+
|
459 |
+
if ( isset($src_attr[2]) && ! empty($src_attr[2]) ) {
|
460 |
+
// get img alt attribute from the first image found
|
461 |
+
$alt = '';
|
462 |
+
preg_match('/(alt)="([^"]*)"/i', $img[0], $alt_attr);
|
463 |
+
|
464 |
+
if ( isset($alt_attr[2]) && !empty($alt_attr[2]) ) {
|
465 |
+
$alt = $alt_attr[2];
|
466 |
+
}
|
467 |
+
|
468 |
+
// image from Media Library
|
469 |
+
if ( $attachment_id = $this->get_attachment_id($src_attr[2]) ) {
|
470 |
+
return [
|
471 |
+
'path' => get_attached_file($attachment_id),
|
472 |
+
'alt' => $alt
|
473 |
+
];
|
474 |
+
} // external image?
|
475 |
+
else {
|
476 |
+
return [
|
477 |
+
'path' => $this->fetch_external_image($id, $src_attr[2]),
|
478 |
+
'alt' => $alt
|
479 |
+
];
|
480 |
+
}
|
481 |
+
}
|
482 |
+
}
|
483 |
+
}
|
484 |
+
}
|
485 |
+
|
486 |
+
return false;
|
487 |
+
}
|
488 |
+
|
489 |
+
/**
|
490 |
+
* Gets image ALT attribute.
|
491 |
+
*
|
492 |
+
* @since 5.0.0
|
493 |
+
* @access private
|
494 |
+
* @param int $id Post ID
|
495 |
+
* @param string $source Image source
|
496 |
+
* @return string
|
497 |
+
*/
|
498 |
+
private function get_alt_attribute($id, $source)
|
499 |
+
{
|
500 |
+
$alt = '';
|
501 |
+
|
502 |
+
// get thumbnail path from the Featured Image
|
503 |
+
if ( "featured" == $source ) {
|
504 |
+
if ( $thumbnail_id = get_post_thumbnail_id($id) ) {
|
505 |
+
// image path
|
506 |
+
$alt = get_post_meta($thumbnail_id, '_wp_attachment_image_alt', true);
|
507 |
+
}
|
508 |
+
}
|
509 |
+
// get thumbnail path from first image attachment
|
510 |
+
elseif ( "first_attachment" == $source ) {
|
511 |
+
$args = [
|
512 |
+
'numberposts' => 1,
|
513 |
+
'order' => 'ASC',
|
514 |
+
'post_parent' => $id,
|
515 |
+
'post_type' => 'attachment',
|
516 |
+
'post_mime_type' => 'image'
|
517 |
+
];
|
518 |
+
$post_attachments = get_children($args);
|
519 |
+
|
520 |
+
if ( ! empty($post_attachments) ) {
|
521 |
+
$first_img = array_shift($post_attachments);
|
522 |
+
$alt = get_post_meta($first_img->ID, '_wp_attachment_image_alt', true);
|
523 |
+
}
|
524 |
+
}
|
525 |
+
// get thumbnail path from post content
|
526 |
+
elseif ( "first_image" == $source ) {
|
527 |
+
/** @var wpdb $wpdb */
|
528 |
+
global $wpdb;
|
529 |
+
|
530 |
+
if ( $content = $wpdb->get_var("SELECT post_content FROM {$wpdb->posts} WHERE ID = {$id};") ) {
|
531 |
+
// at least one image has been found
|
532 |
+
if ( preg_match('/<img[^>]+>/i', $content, $img) ) {
|
533 |
+
// get img alt attribute from the first image found
|
534 |
+
preg_match('/(alt)="([^"]*)"/i', $img[0], $alt_attr);
|
535 |
+
|
536 |
+
if ( isset($alt_attr[2]) && !empty($alt_attr[2]) ) {
|
537 |
+
$alt = $alt_attr[2];
|
538 |
+
}
|
539 |
+
}
|
540 |
+
}
|
541 |
+
}
|
542 |
+
|
543 |
+
return $alt;
|
544 |
+
}
|
545 |
+
|
546 |
+
/**
|
547 |
+
* Get the Attachment ID for a given image URL.
|
548 |
+
*
|
549 |
+
* @since 3.0.0
|
550 |
+
* @access private
|
551 |
+
* @author Frankie Jarrett
|
552 |
+
* @link http://frankiejarrett.com/get-an-attachment-id-by-url-in-wordpress/
|
553 |
+
* @param string $url
|
554 |
+
* @return int|null
|
555 |
+
*/
|
556 |
+
private function get_attachment_id($url)
|
557 |
+
{
|
558 |
+
$url = Helper::add_scheme(
|
559 |
+
$url,
|
560 |
+
is_ssl() ? 'https://' : 'http://'
|
561 |
+
);
|
562 |
+
|
563 |
+
// Split the $url into two parts with the wp-content directory as the separator.
|
564 |
+
$parse_url = explode(parse_url(WP_CONTENT_URL, PHP_URL_PATH), $url);
|
565 |
+
|
566 |
+
// Get the host of the current site and the host of the $url, ignoring www.
|
567 |
+
$this_host = str_ireplace('www.', '', parse_url(home_url(), PHP_URL_HOST));
|
568 |
+
$file_host = str_ireplace('www.', '', parse_url($url, PHP_URL_HOST));
|
569 |
+
|
570 |
+
// Return nothing if there aren't any $url parts or if the current host and $url host do not match.
|
571 |
+
if (
|
572 |
+
! isset($parse_url[1])
|
573 |
+
|| empty($parse_url[1])
|
574 |
+
|| ($this_host != $file_host)
|
575 |
+
) {
|
576 |
+
return false;
|
577 |
+
}
|
578 |
+
|
579 |
+
// Now we're going to quickly search the DB for any attachment GUID with a partial path match.
|
580 |
+
// Example: /uploads/2013/05/test-image.jpg
|
581 |
+
global $wpdb;
|
582 |
+
|
583 |
+
if ( ! $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parse_url[1])) ) {
|
584 |
+
// Maybe it's a resized image, so try to get the full one
|
585 |
+
$parse_url[1] = preg_replace('/-[0-9]{1,4}x[0-9]{1,4}\.(jpg|jpeg|png|gif|bmp)$/i', '.$1', $parse_url[1]);
|
586 |
+
$attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM {$wpdb->prefix}posts WHERE guid RLIKE %s;", $parse_url[1]));
|
587 |
+
}
|
588 |
+
|
589 |
+
// Returns null if no attachment is found.
|
590 |
+
return isset($attachment[0]) ? $attachment[0] : NULL;
|
591 |
+
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* Fetchs external images.
|
595 |
+
*
|
596 |
+
* @since 2.3.3
|
597 |
+
* @access private
|
598 |
+
* @param int $id Post ID.
|
599 |
+
* @param string $url Image url.
|
600 |
+
* @return string|bool Image path, or false on failure.
|
601 |
+
*/
|
602 |
+
private function fetch_external_image($id, $url)
|
603 |
+
{
|
604 |
+
$full_image_path = trailingslashit($this->get_plugin_uploads_dir()['basedir']) . "{$id}_" . sanitize_file_name(rawurldecode(wp_basename($url)));
|
605 |
+
|
606 |
+
// if the file exists already, return URL and path
|
607 |
+
if ( file_exists($full_image_path) )
|
608 |
+
return $full_image_path;
|
609 |
+
|
610 |
+
$url = Helper::add_scheme(
|
611 |
+
$url,
|
612 |
+
is_ssl() ? 'https://' : 'http://'
|
613 |
+
);
|
614 |
+
|
615 |
+
$accepted_status_codes = [200, 301, 302];
|
616 |
+
$response = wp_remote_head($url, ['timeout' => 5, 'sslverify' => false]);
|
617 |
+
|
618 |
+
if (
|
619 |
+
! is_wp_error($response)
|
620 |
+
&& in_array(wp_remote_retrieve_response_code($response), $accepted_status_codes)
|
621 |
+
) {
|
622 |
+
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
623 |
+
|
624 |
+
$url = str_replace('https://', 'http://', $url);
|
625 |
+
$tmp = download_url($url);
|
626 |
+
|
627 |
+
// File was downloaded successfully
|
628 |
+
if ( ! is_wp_error($tmp) ) {
|
629 |
+
// Determine image type
|
630 |
+
if ( function_exists('exif_imagetype') ) {
|
631 |
+
$image_type = exif_imagetype($tmp);
|
632 |
+
} else {
|
633 |
+
$image_type = getimagesize($tmp);
|
634 |
+
$image_type = ( isset($image_type[2]) ) ? $image_type[2] : NULL;
|
635 |
+
}
|
636 |
+
|
637 |
+
// Valid image, save it
|
638 |
+
if ( in_array($image_type, [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG]) ) {
|
639 |
+
// move file to Uploads
|
640 |
+
if ( @rename($tmp, $full_image_path) ) {
|
641 |
+
// borrowed from WP - set correct file permissions
|
642 |
+
$stat = stat(dirname($full_image_path));
|
643 |
+
$perms = $stat['mode'] & 0000644;
|
644 |
+
@chmod($full_image_path, $perms);
|
645 |
+
|
646 |
+
return $full_image_path;
|
647 |
+
}
|
648 |
+
}
|
649 |
+
|
650 |
+
// Invalid file, remove it
|
651 |
+
@unlink($tmp);
|
652 |
+
}
|
653 |
+
}
|
654 |
+
|
655 |
+
return false;
|
656 |
+
}
|
657 |
+
|
658 |
+
/**
|
659 |
+
* Resizes image.
|
660 |
+
*
|
661 |
+
* @since 3.0.0
|
662 |
+
* @access private
|
663 |
+
* @param string $path Image path
|
664 |
+
* @param string $filename Image filename
|
665 |
+
* @param array $size Image size
|
666 |
+
* @param bool $crop Whether to crop the image or not
|
667 |
+
* @return string|bool Image URL on success, false on error
|
668 |
+
*/
|
669 |
+
private function resize($path, $filename, $size, $crop = true)
|
670 |
+
{
|
671 |
+
$image = wp_get_image_editor($path);
|
672 |
+
|
673 |
+
// valid image, create thumbnail
|
674 |
+
if ( ! is_wp_error($image) ) {
|
675 |
+
/**
|
676 |
+
* Hook to change the image compression quality of WPP's thumbnails.
|
677 |
+
* @since 4.2.1
|
678 |
+
*/
|
679 |
+
$quality = apply_filters('wpp_thumbnail_compression_quality', null);
|
680 |
+
|
681 |
+
if ( ! ctype_digit($quality) )
|
682 |
+
$quality = null; // Fallback to core's default
|
683 |
+
|
684 |
+
$image->set_quality($quality);
|
685 |
+
|
686 |
+
$image->resize($size[0], $size[1], $crop);
|
687 |
+
$new_img = $image->save(trailingslashit($this->get_plugin_uploads_dir()['basedir']) . $filename);
|
688 |
+
|
689 |
+
if ( ! is_wp_error($new_img) )
|
690 |
+
return trailingslashit($this->get_plugin_uploads_dir()['baseurl']) . $filename;
|
691 |
+
}
|
692 |
+
|
693 |
+
return false;
|
694 |
+
}
|
695 |
+
|
696 |
+
/**
|
697 |
+
* Render image tag.
|
698 |
+
*
|
699 |
+
* @since 3.0.0
|
700 |
+
* @access public
|
701 |
+
* @param string $src Image URL
|
702 |
+
* @param array $dimension Image's width and height
|
703 |
+
* @param string $class CSS class
|
704 |
+
* @param object $alt Alternative text
|
705 |
+
* @param string $error Error, if the image could not be created
|
706 |
+
* @return string
|
707 |
+
*/
|
708 |
+
public function render($src, $size, $class, $alt = '', $error = null)
|
709 |
+
{
|
710 |
+
$img_tag = '';
|
711 |
+
|
712 |
+
if ( $error ) {
|
713 |
+
$img_tag = '<!-- ' . $error . ' --> ';
|
714 |
+
}
|
715 |
+
|
716 |
+
$src = 'src="' . esc_url(is_ssl() ? str_ireplace("http://", "https://", $src) : $src) . '"';
|
717 |
+
$lazyload = ( $this->admin_options['tools']['thumbnail']['lazyload'] ) ? ' loading="lazy"' : '';
|
718 |
+
|
719 |
+
$img_tag .= '<img ' . $src . ' width="' . $size[0] . '" height="' . $size[1] . '" alt="' . esc_attr($alt) . '" class="' . esc_attr($class) . '"' . $lazyload . ' />';
|
720 |
+
|
721 |
+
return apply_filters('wpp_render_image', $img_tag);
|
722 |
+
}
|
723 |
+
|
724 |
+
/**
|
725 |
+
* Gets list of available thumbnails sizes
|
726 |
+
*
|
727 |
+
* @since 3.2.0
|
728 |
+
* @link http://codex.wordpress.org/Function_Reference/get_intermediate_image_sizes
|
729 |
+
* @param string $size
|
730 |
+
* @return array|bool
|
731 |
+
*/
|
732 |
+
public function get_sizes($size = '')
|
733 |
+
{
|
734 |
+
if ( ! is_array($this->available_sizes) || empty($this->available_sizes) ) {
|
735 |
+
global $_wp_additional_image_sizes;
|
736 |
+
|
737 |
+
$this->available_sizes = [];
|
738 |
+
$get_intermediate_image_sizes = get_intermediate_image_sizes();
|
739 |
+
|
740 |
+
// Create the full array with sizes and crop info
|
741 |
+
foreach( $get_intermediate_image_sizes as $_size ) {
|
742 |
+
if ( in_array($_size, ['thumbnail', 'medium', 'large']) ) {
|
743 |
+
$this->available_sizes[$_size]['width'] = get_option($_size . '_size_w');
|
744 |
+
$this->available_sizes[$_size]['height'] = get_option($_size . '_size_h');
|
745 |
+
$this->available_sizes[$_size]['crop'] = (bool) get_option($_size . '_crop');
|
746 |
+
} elseif ( isset($_wp_additional_image_sizes[$_size]) ) {
|
747 |
+
$this->available_sizes[$_size] = [
|
748 |
+
'width' => $_wp_additional_image_sizes[$_size]['width'],
|
749 |
+
'height' => $_wp_additional_image_sizes[$_size]['height'],
|
750 |
+
'crop' => $_wp_additional_image_sizes[$_size]['crop']
|
751 |
+
];
|
752 |
+
}
|
753 |
+
}
|
754 |
+
}
|
755 |
+
|
756 |
+
// Get only 1 size if found
|
757 |
+
if ( $size ) {
|
758 |
+
if ( isset($this->available_sizes[$size]) ) {
|
759 |
+
return $this->available_sizes[$size];
|
760 |
+
}
|
761 |
+
return false;
|
762 |
+
}
|
763 |
+
|
764 |
+
return $this->available_sizes;
|
765 |
+
}
|
766 |
+
|
767 |
+
/**
|
768 |
+
* Returns the URL of the default thumbnail image.
|
769 |
+
*
|
770 |
+
* @since 5.0.0
|
771 |
+
* @param int|null
|
772 |
+
* @return string
|
773 |
+
*/
|
774 |
+
public function get_default_url($post_ID = null)
|
775 |
+
{
|
776 |
+
if ( has_filter('wpp_default_thumbnail_url') ) {
|
777 |
+
$default_thumbnail_url = apply_filters('wpp_default_thumbnail_url', $this->default_thumbnail, $post_ID);
|
778 |
+
|
779 |
+
if ( $default_thumbnail_url != $this->default_thumbnail && $this->is_image_url($default_thumbnail_url) )
|
780 |
+
return $default_thumbnail_url;
|
781 |
+
}
|
782 |
+
|
783 |
+
return $this->default_thumbnail;
|
784 |
+
}
|
785 |
+
|
786 |
+
/**
|
787 |
+
* Checks whether an URL points to an actual image.
|
788 |
+
*
|
789 |
+
* @since 5.0.0
|
790 |
+
* @access private
|
791 |
+
* @param string
|
792 |
+
* @return array|bool
|
793 |
+
*/
|
794 |
+
private function is_image_url($url)
|
795 |
+
{
|
796 |
+
if ( ! filter_var($url, FILTER_VALIDATE_URL) )
|
797 |
+
return false;
|
798 |
+
|
799 |
+
// sanitize URL, just in case
|
800 |
+
$image_url = esc_url($url);
|
801 |
+
// remove querystring
|
802 |
+
preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $image_url, $matches);
|
803 |
+
|
804 |
+
return ( is_array($matches) && ! empty($matches) ) ? $matches : false;
|
805 |
+
}
|
806 |
+
}
|
wordpress-popular-posts.php
CHANGED
@@ -1,60 +1,60 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* The plugin bootstrap file
|
5 |
-
*
|
6 |
-
* This file is read by WordPress to generate the plugin information in the plugin
|
7 |
-
* admin area. This file also includes all of the dependencies used by the plugin,
|
8 |
-
* registers the activation and deactivation functions, and defines a function
|
9 |
-
* that starts the plugin.
|
10 |
-
*
|
11 |
-
* @link https://cabrerahector.com/
|
12 |
-
* @since 4.0.0
|
13 |
-
* @package WordPressPopularPosts
|
14 |
-
*
|
15 |
-
* @wordpress-plugin
|
16 |
-
* Plugin Name: WordPress Popular Posts
|
17 |
-
* Plugin URI: https://wordpress.org/plugins/wordpress-popular-posts/
|
18 |
-
* Description: A highly customizable widget that displays the most popular posts on your blog.
|
19 |
-
* Version: 5.2.
|
20 |
-
* Author: Hector Cabrera
|
21 |
-
* Author URI: https://cabrerahector.com/
|
22 |
-
* License: GPL-2.0+
|
23 |
-
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
24 |
-
* Text Domain: wordpress-popular-posts
|
25 |
-
* Domain Path: /languages
|
26 |
-
*/
|
27 |
-
|
28 |
-
if ( ! defined( 'WPINC' ) ) {
|
29 |
-
die();
|
30 |
-
}
|
31 |
-
|
32 |
-
define('WPP_VERSION', '5.2.
|
33 |
-
define('WPP_MIN_PHP_VERSION', '5.4');
|
34 |
-
define('WPP_MIN_WP_VERSION', '4.9');
|
35 |
-
|
36 |
-
/** Requirements check */
|
37 |
-
global $wp_version;
|
38 |
-
|
39 |
-
// We're good, continue!
|
40 |
-
if ( version_compare(PHP_VERSION, WPP_MIN_PHP_VERSION, '>=') && version_compare($wp_version, WPP_MIN_WP_VERSION, '>=') ) {
|
41 |
-
$wpp_main_plugin_file = __FILE__;
|
42 |
-
// Load plugin bootstrap
|
43 |
-
require __DIR__ . '/src/Bootstrap.php';
|
44 |
-
} // Nope.
|
45 |
-
else {
|
46 |
-
if ( isset($_GET['activate']) )
|
47 |
-
unset($_GET['activate']);
|
48 |
-
|
49 |
-
function wpp_render_min_requirements_notice() {
|
50 |
-
global $wp_version;
|
51 |
-
echo '<div class="notice notice-error"><p>' . sprintf(
|
52 |
-
__('WordPress Popular Posts requires at least PHP %1$s and WordPress %2$s to function correctly. Your site uses PHP %3$s and WordPress %4$s.', 'wordpress-popular-posts'),
|
53 |
-
WPP_MIN_PHP_VERSION,
|
54 |
-
WPP_MIN_WP_VERSION,
|
55 |
-
PHP_VERSION,
|
56 |
-
$wp_version
|
57 |
-
) . '</p></div>';
|
58 |
-
}
|
59 |
-
add_action('admin_notices', 'wpp_render_min_requirements_notice');
|
60 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* The plugin bootstrap file
|
5 |
+
*
|
6 |
+
* This file is read by WordPress to generate the plugin information in the plugin
|
7 |
+
* admin area. This file also includes all of the dependencies used by the plugin,
|
8 |
+
* registers the activation and deactivation functions, and defines a function
|
9 |
+
* that starts the plugin.
|
10 |
+
*
|
11 |
+
* @link https://cabrerahector.com/
|
12 |
+
* @since 4.0.0
|
13 |
+
* @package WordPressPopularPosts
|
14 |
+
*
|
15 |
+
* @wordpress-plugin
|
16 |
+
* Plugin Name: WordPress Popular Posts
|
17 |
+
* Plugin URI: https://wordpress.org/plugins/wordpress-popular-posts/
|
18 |
+
* Description: A highly customizable widget that displays the most popular posts on your blog.
|
19 |
+
* Version: 5.2.3
|
20 |
+
* Author: Hector Cabrera
|
21 |
+
* Author URI: https://cabrerahector.com/
|
22 |
+
* License: GPL-2.0+
|
23 |
+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
24 |
+
* Text Domain: wordpress-popular-posts
|
25 |
+
* Domain Path: /languages
|
26 |
+
*/
|
27 |
+
|
28 |
+
if ( ! defined( 'WPINC' ) ) {
|
29 |
+
die();
|
30 |
+
}
|
31 |
+
|
32 |
+
define('WPP_VERSION', '5.2.3');
|
33 |
+
define('WPP_MIN_PHP_VERSION', '5.4');
|
34 |
+
define('WPP_MIN_WP_VERSION', '4.9');
|
35 |
+
|
36 |
+
/** Requirements check */
|
37 |
+
global $wp_version;
|
38 |
+
|
39 |
+
// We're good, continue!
|
40 |
+
if ( version_compare(PHP_VERSION, WPP_MIN_PHP_VERSION, '>=') && version_compare($wp_version, WPP_MIN_WP_VERSION, '>=') ) {
|
41 |
+
$wpp_main_plugin_file = __FILE__;
|
42 |
+
// Load plugin bootstrap
|
43 |
+
require __DIR__ . '/src/Bootstrap.php';
|
44 |
+
} // Nope.
|
45 |
+
else {
|
46 |
+
if ( isset($_GET['activate']) )
|
47 |
+
unset($_GET['activate']);
|
48 |
+
|
49 |
+
function wpp_render_min_requirements_notice() {
|
50 |
+
global $wp_version;
|
51 |
+
echo '<div class="notice notice-error"><p>' . sprintf(
|
52 |
+
__('WordPress Popular Posts requires at least PHP %1$s and WordPress %2$s to function correctly. Your site uses PHP %3$s and WordPress %4$s.', 'wordpress-popular-posts'),
|
53 |
+
WPP_MIN_PHP_VERSION,
|
54 |
+
WPP_MIN_WP_VERSION,
|
55 |
+
PHP_VERSION,
|
56 |
+
$wp_version
|
57 |
+
) . '</p></div>';
|
58 |
+
}
|
59 |
+
add_action('admin_notices', 'wpp_render_min_requirements_notice');
|
60 |
+
}
|