Custom Facebook Feed - Version 2.15

Version Description

  • New: Added a new visual header option which displays the cover photo, avatar, page name, bio, and number of likes from your Facebook page at the top of your feeds. To enable the header, go to Facebook Feed > Customize > General > Header > Header Type > Visual.
  • New: To help us improve the plugin we've added the ability to opt-in to usage tracking so that we can understand what features and settings are being used, and which features matter to you the most. This is disabled by default and will only be enabled if you explictly choose to opt in. If opted in, the plugin will send a report in the background once per week with your plugin settings and basic information about your website environment. No personal or sensitive data is collected (such as email addresses, Instagram account information, license keys, etc). To enable or disable usage tracking at a later date use the setting at: Instagram Feed > Customize > Advanced > Misc > Enable Usage Tracking. See here for more information.
  • New: Added a setting to display a different number of posts on mobile devices vs desktop. While on the configure tab, check the box "Show different number for mobile" to reveal the setting.
  • New: Added capability "manage_custom_facebook_feed_options". Users with this capability can make changes to Facebook Feed settings and view admin only messages.
  • New: Added a PHP filter "cff_post_text" to change the post text before outputting it in the feed HTML.
Download this release

Release Info

Developer smashballoon
Plugin Icon 128x128 Custom Facebook Feed
Version 2.15
Comparing to
See all releases

Code changes from version 2.14.1 to 2.15

README.txt CHANGED
@@ -1,98 +1,93 @@
1
- === Smash Balloon Social Post Feed ===
2
- Contributors: smashballoon
3
- Tags: Facebook, Facebook feed, Facebook posts, Facebook wall, Facebook page, Custom Facebook Feed, Facebook group, Facebook social feed, Facebook post, Facebook like box
4
Requires at least: 3.0
5
Requires PHP: 5.2
6
Tested up to: 5.4
7
- Stable tag: 2.14.1
8
License: GPLv2 or later
9
License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
11
- Formerly "Custom Facebook Feed". Display completely customizable Facebook feeds of any public Facebook page on your website.
12
13
== Description ==
14
15
- Display Facebook posts on your website. **Completely customizable**, **responsive** and **search engine crawlable** Facebook feeds. Display **multiple Facebook feeds** from **any public Facebook page**, and completely match the look and feel of the site with tons of Facebook feed customization options!
16
17
- *"The perfect Facebook plugin with amazing support! What else do you want? Get it!"* - [JoeJeffries](http://wordpress.org/support/topic/you-dont-already-have-this?facebook)
18
19
- *"I honestly cannot recommend this Facebook plugin enough. The plugin itself is gorgeous and super customizable, and if you run into trouble...support will get you out of it. Five Stars across the board."* - [pamsavoybarnett](http://wordpress.org/support/topic/love-this-plugin-w-awesome-support?facebook)
20
21
- **Please note:** This free Facebook plugin allows you to display text and links from Facebook posts. To display **photos, videos, comments,** and more, we offer a Pro version of the plugin. See the Pro Version section below for more information.
22
23
- ### Facebook Feed Features
24
25
- * **Super simple to set up** - 1 minute quick setup with no Facebook Developer App required
26
- * **Display feeds from ANY Facebook page** - even Facebook pages you aren't an admin of
27
- * **Completely Customizable** - By default the Facebook feed will adopt the style of your website, but your Facebook feeds can be completely customized to look however you like - with tons of styling and customization options!
28
- * Facebook feed content is **crawlable by search engines** adding SEO value to your site - other Facebook plugins embed the feed using iframes which are not crawlable
29
- * Completely **responsive** and mobile optimized Facebook feeds - layout looks great on any screen size and in any container width
30
- * Display **feeds from multiple different Facebook pages** and use the shortcode to embed your Facebook feeds into a page, post or widget anywhere on your site
31
- * **Caching** means that your Facebook posts load lightning fast. Set your own caching time - check for new posts on Facebook every few seconds, minutes, hours or days. You decide.
32
- * Show and hide certain parts of each Facebook post
33
- * Show or hide the Facebook profile picture and name of the author above each Facebook post
34
- * Display Facebook posts by just the page owner, everyone who posts on your Facebook page, or only other people
35
- * Control the width, height, padding and background color of your Facebook feed
36
- * Customize the size, weight and color of text in your Facebook posts
37
- * Choose to set a background color and rounded corners on your Facebook posts
38
- * Supports Facebook tags - creates links when using the @ symbol to tag people in your Facebook posts
39
- * Automatically links hashtags used in posts to the hashtag page on Facebook
40
- * Select the number of Facebook posts to display in your Facebook feed
41
- * Use the shortcode options to style multiple Facebook feeds in completely different ways
42
- * Set a maximum character length for both the text and descriptions of your Facebook posts
43
- * Create a customizable Facebook header with a range of icons for your Custom Facebook Feed
44
- * Localization/i18n support to allow every part of the Facebook feed to be displayed in your language
45
- * Add your own **custom CSS**
46
47
### Pro Version (Custom Facebook Feed Pro)
48
49
- In order to maintain the free version of the Custom Facebook Feed plugin on an ongoing basis, and to provide quick and effective support for free, we offer a Pro version of the plugin. Custom Facebook Feed Pro allows you to display photos, videos, the number of likes, shares, reactions and comments for each Facebook post, choose from multiple layout options, filter Facebook posts by type or #hashtag/string, load more Facebook posts into your feed, and more. [Click here](https://smashballoon.com/differences-between-the-free-version-and-pro-version-of-the-custom-facebook-feed-plugin/ "Differences between free and Pro version of Custom Facebook Feed plugin") for a full list of all differences between the Custom Facebook Feed free and Pro versions.
50
51
- * [Find out more about Custom Facebook Feed Pro](https://smashballoon.com/custom-facebook-feed/?utm_campaign=facebook-free-readme&utm_source=proversion&utm_medium=findout "Custom Facebook Feed Pro")
52
- * [Try out the Custom Facebook Feed Pro demo](https://smashballoon.com/custom-facebook-feed/demo/?utm_campaign=facebook-free-readme&utm_source=proversion&utm_medium=demo "Custom Facebook Feed Pro Demo").
53
54
- ### Benefits
55
56
* **Increase social engagement** between you and your users, customers, or fans
57
- * **Save time** by using the Custom Facebook Feed to generate dynamic, search engine crawlable content on your website
58
* **Get more likes** by displaying your Facebook content directly on your site
59
- * **Improve your SEO** as all of that quality keyword-rich Facebook content from posts and Facebook comments is directly embedded into your website
60
* Display your Facebook content your way to perfectly match your website's style
61
* **No Coding Required** - choose from tons of built-in customization options to create a truly unique feed of your Facebook content.
62
- * The Custom Facebook Feed plugin is **updated regularly** with new features, bug-fixes and Facebook API changes
63
* Support is quick and effective
64
* We're dedicated to providing the **most customizable**, **robust** and **well supported** Facebook feed plugin in the world!
65
66
- ### How to use the Custom Facebook Feed plugin
67
68
- One of our main priorities has always been to make our Custom Facebook Feed plugin as easy as possible to setup and use. Once you've installed the plugin there are only a few steps to get up and running:
69
70
- * 1) Click the big blue Facebook button on the plugin settings page. This will prompt you to log into your Facebook account to authorize the plugin.
71
- * 2) Once you've connected your Facebook account, save the plugin settings.
72
- * 3) Then simply copy and paste the `[custom-facebook-feed]` shortcode onto any page, post, or widget where you want the Facebook feed to be displayed.
73
74
- That's it! You can then customize the Facebook feed as needed using the settings on the Facebook Feed > Customize page.
75
76
- For full step-by-step setup directions with screenshots, see [here](https://smashballoon.com/custom-facebook-feed/docs/free/?utm_campaign=facebook-free-readme&utm_source=howto&utm_medium=setup "Custom Facebook Feed Free Setup Doc").
77
78
### Requesting support
79
80
- Customer support is a huge deal to us. We pride ourselves on always providing quick, effective, and courteous support to all of our users. If you're having an issue using the Custom Facebook Feed plugin then just let us know and we'll be there to help as soon as possible. You can either open a ticket on the support forum on [WordPress.org](https://wordpress.org/support/plugin/custom-facebook-feed/ "Custom Facebook Feed Free support forum"), or directly on the Custom Facebook Feed section of [our website](https://smashballoon.com/custom-facebook-feed/support/ "Custom Facebook Feed website support form"). We also have a large collection of help documentation and FAQs [on our website](https://smashballoon.com/custom-facebook-feed/faq/ "Custom Facebook Feed support FAQs") for all common issues related to the Custom Facebook Feed plugin.
81
82
### Who's behind this plugin?
83
84
We're Smash Balloon; a fun-loving WordPress plugin development company birthed into existence in early 2013. We specialize in creating social media plugins that are not only intuitive and simple to use, but also designed to integrate seamlessly into your website and allow you to display your social media content in powerful and unique ways. Over 1 million awesome people have decided to actively use our free plugins, which is an incredible honor that we don't take lightly. This compels us to try to provide the quickest and most effective customer support that we can, blowing users away with the best customer service they've ever experienced.
85
86
- To find out more about the team, see [here](https://smashballoon.com/about/?utm_campaign=facebook-free-readme&utm_source=who&utm_medium=about "Team Smash Balloon").
87
-
88
- Check out our other free plugins for [Instagram](https://wordpress.org/plugins/instagram-feed "Instagram Feed free plugin"), [Twitter](https://wordpress.org/plugins/custom-twitter-feeds/ "Custom Twitter Feeds free plugin"), and [YouTube](https://wordpress.org/plugins/feeds-for-youtube/ "Feeds for YouTube free plugin").
89
90
== Installation ==
91
92
- 1. Install the Custom Facebook Feed either via the WordPress plugin directory, or by uploading the files to your web server (in the `/wp-content/plugins/` directory).
93
2. Activate the plugin through the 'Plugins' menu in WordPress.
94
3. Navigate to the 'Facebook Feed' settings page to configure your feed.
95
- 4. Use the shortcode `[custom-facebook-feed]` in your page, post or widget to display your feed.
96
5. You can display multiple feeds of different Facebook pages by specifying a Page ID directly in the shortcode: `[custom-facebook-feed id=smashballoon num=5]`.
97
98
== Frequently Asked Questions ==
@@ -101,164 +96,76 @@ For a full list of FAQs and help with troubleshooting please visit the **[FAQ &
101
102
= How do I find the Page ID of my Facebook page? =
103
104
- If you have a Facebook **page** with a URL like this: `https://www.facebook.com/smashballoon` then the Page ID is just `smashballoon`. If your page URL is structured like this: `https://www.facebook.com/pages/smashballoon/123654123654123` then the Page ID is actually the number at the end, so in this case `123654123654123`.
105
-
106
- Due to [recent changes](https://smashballoon.com/facebook-api-changes-april-4-2018/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=id) to the Facebook API it is unfortunately no longer possible to display a feed from a Facebook Group.
107
108
Copy and paste the ID into the [Pro demo](https://smashballoon.com/custom-facebook-feed/demo/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=demoid) to test it.
109
110
- = Are there any limitations on which Facebook page or group feeds I can display? =
111
-
112
- The Facebook feed you're trying to display has to be from a publicly accessible Facebook page. This means that you can't display the feed from your own personal Facebook profile or Facebook group. This is to do with Facebook's privacy policies. You can't display a non-public Facebook feed publicly.
113
-
114
- If your Facebook page has any restrictions on it (age, for example) then it means that people have to be signed into Facebook in order to view your page. This isn't desirable for most Facebook pages as it means that it isn't accessible by people who don't have a Facebook account and that your Facebook page can't be crawled and indexed by search engines.
115
-
116
- An easy way to determine whether your Facebook page is set to public is to sign out of your Facebook account and try to visit your page. If Facebook forces you to sign in to view your page then it isn't public. You can change your Facebook page to public in your Facebook page settings simply by removing any age or location restrictions you have on it ([screenshot](https://smashballoon.com/wp-content/uploads/2013/06/facebook-page-restrictions.png)), which will then allow the Custom Facebook Feed plugin to access and display your feed.
117
-
118
- = Can I display feeds from multiple Facebook pages? =
119
-
120
- You can set your default Facebook Page ID on the Custom Facebook Feed settings page within the WordPress admin, you can then define different page IDs in the shortcodes you use to show multiple feeds from different Facebook pages. Just use the id option in your shortcode like so: [custom-facebook-feed id=another_page_id]. You can use as many shortcodes as you like with as many different IDs as you like.
121
-
122
- = Can I display the feed from a personal Facebook profile? =
123
-
124
- Due to Facebook's privacy policy you're not able to use the plugin to display all of your posts from a personal profile, only from a public page, as posts from a personal profile are protected for privacy reasons. You may have limited success in displaying certain posts from a personal profile but most posts are not able to be displayed.
125
-
126
- If you're using the profile to represent a business, organization, product, public figure or the like, then we'd advise converting your profile to a page per [Facebook's recommendation](http://www.facebook.com/help/175644189234902/), as there are many advantages to using pages over profiles.
127
-
128
- Once you've done so, the plugin will be able to retrieve and display all of your posts.
129
-
130
- = Can I show photos and videos in my Custom Facebook feed? =
131
-
132
- This free plugin only allows you to display text from your Facebook posts. To display photos and videos in your feed you would need to upgrade to the Pro version of the plugin. Try out a demo of the Pro version on the [Custom Facebook Feed website](https://smashballoon.com/custom-facebook-feed/demo/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=media "Custom Facebook Feed Demo"), and find out more about the Pro version [here](https://smashballoon.com/custom-facebook-feed/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=pro "Custom Facebook Feed Pro"). [Click here](https://smashballoon.com/differences-between-the-free-version-and-pro-version-of-the-custom-facebook-feed-plugin/ "Differences between free and Pro version of Custom Facebook Feed plugin") for a full list of all differences between the free version and Pro version.
133
-
134
- = Can I show the comments, shares and likes associated with each Facebook post? =
135
-
136
- This is a feature of the [Pro version of the plugin](https://smashballoon.com/custom-facebook-feed/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=comments "Custom Facebook Feed Pro"). To display comments, shares and likes you would need to upgrade from the free version to the Pro version.
137
-
138
- = Is the content of my Custom Facebook Feed crawlable by search engines? =
139
-
140
- It sure is. Unlike other Facebook plugins which use iframes to embed your Facebook feed into your page once it's loaded, the Custom Facebook Feed uses PHP to embed your Facebook feed content directly into your page. This adds dynamic, search engine crawlable content to your site.
141
-
142
- = How do I embed the Custom Facebook Feed directly into a WordPress page template? =
143
144
- You can embed your Facebook feed directly into a template file by using the WordPress [do_shortcode](http://codex.wordpress.org/Function_Reference/do_shortcode "WordPress.org do_shortcode reference") function: `<?php echo do_shortcode('[custom-facebook-feed]'); ?>`.
145
146
- = My Facebook feed posts are not showing up, or all I can see is the Facebook Like box but no posts =
147
148
- Please refer to [this FAQ](https://smashballoon.com/facebook-feed-doesnt-show-can-see-like-box-posts-gives/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=errors "My Facebook feed posts are not showing up, or all I can see is the Facebook Like box but no posts") for potential solutions on how to resolve this issue.
149
150
- = Create a basic slideshow from your Facebook posts =
151
152
- The Custom Facebook Feed plugin doesn't currently have a slideshow feature built into it, but it's possible to achieve a basic slideshow by doing the following:
153
154
- 1) Add a class to the shortcode of the Facebook feed that you want to convert into a slideshow:
155
156
- `[custom-facebook-feed class="slideshow"]`
157
158
- 2) Set the number of posts to display to be the number of Facebook posts you want to include in the slideshow (10 for example). You can do this by using the `num` shortcode option:
159
160
- `[custom-facebook-feed class="slideshow" num=10]`
161
162
- 3) Add the following to the plugin's **Custom JavaScript** section, which is under the 'Misc' tab on the plugin's 'Customize' page. Please note, if you change the class option in the shortcode above to be anything but "slideshow" then make sure to change that on the first line of the snippet below:
163
164
- `var shortcodeClass = 'slideshow',
165
- cffSpeed = 5000,
166
- $cff = $('#cff.'+ shortcodeClass);
167
- $cffItem = $cff.find('.cff-item'),
168
- cffNum = $cffItem.length,
169
- cffCur = 0;
170
- $cffItem.hide();
171
- setTimeout(function(){ $cff.find('.cff-item').eq(0).show(); }, 200);
172
- setInterval(function(){
173
- $cff.find('.cff-item').eq(cffCur).fadeOut( "fast", function() {
174
- if( cffCur == cffNum-1 ) cffCur = -1;
175
- cffCur++;
176
- $cff.find('.cff-item').eq(cffCur).fadeIn();
177
- });
178
- }, cffSpeed);`
179
-
180
- 4) You can change the speed of the transition by editing the **cffSpeed = 5000** value at the top of the snippet. 5000 is equal to 5 seconds (5000ms).
181
-
182
- = Changing the font in your Facebook feed and using Google Fonts =
183
-
184
- Please refer to [this FAQ](https://smashballoon.com/changing-the-font-in-your-facebook-feed-using-google-fonts/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=fonts "Changing the font in your Facebook feed and using Google Fonts") for directions on how to use Google fonts in your Facebook posts.
185
-
186
- = Can I display my Facebook posts horizontally or in multiple columns? =
187
-
188
- Please refer to [this FAQ](https://smashballoon.com/can-display-facebook-post-horizontally-multiple-columns/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=horizontal "Can I display my Facebook posts horizontally or in multiple columns?") for directions on how to display your Facebook posts in multiple columns.
189
-
190
- = My Facebook feed appears to have stopped updating / working =
191
-
192
- If your Facebook feed doesn't appear to be showing the most recent Facebook posts then the most likely explanation is that the recent Facebook posts in your feed may be shared from a user's personal Facebook profile. Facebook's privacy policy doesn't allow posts that you share from personal Facebook profiles to be shared outside of Facebook as the posts don't technically belong to your Facebook page, they belong to the user who posted it to their personal Facebook profile. There's an example of a post shared from a user's personal Facebook profile [here](https://smashballoon.com/wp-content/uploads/2014/11/sharing-photo-facebook-profile.jpg "Example of Facebook post shared from personal Faceboo profile").
193
-
194
- Please note, this isn't a limitation of our plugin, it's a restriction which Facebook places on it's content in order to protect the privacy of their Facebook users.
195
-
196
- **Potential solutions**
197
-
198
- * You could re-post the Facebook post to your page rather than sharing it to your Facebook page. If you re-post the content as your own post on your Facebook page then the content now originates from your Facebook page and will be displayed in the Facebook feed on your website.
199
-
200
- * If you were to share a post from another Facebook page or public source, rather than sharing it from someone's personal Facebook profile, then it would show up in your feed outside of Facebook, but by default any posts that originate from a personal Facebook profile are protected by Facebook's privacy policy and is the private content of that Facebook profile owner.
201
-
202
- = I'm receiving an error message when trying to display my Facebook posts =
203
-
204
- Please refer to our [Error Message Reference page](https://smashballoon.com/custom-facebook-feed/docs/errors/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=errors "I'm receiving an error message when trying to display my Facebook posts") for information on how to resolve common error messages.
205
-
206
- = Creating a Masonry grid layout from your Facebook posts =
207
-
208
- Please refer to [this FAQ](https://smashballoon.com/creating-a-masonry-grid-layout-from-your-facebook-posts/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=masonry "Creating a Masonry grid layout from your Facebook posts") for directions on how to create a Masonry grid layout from your Facebook feed posts.
209
-
210
- = How do I customize my Facebook feed? =
211
-
212
- You can customize the Facebook feed by setting the options on the Customize page, which can be found under the Facebook Feed menu in your left hand WordPress admin menu. If you need even deeper customization than the built in options allow then you can add your own CSS to the plugin in the Custom CSS section under the Misc tab to further customize your Facebook feed.
213
-
214
- You can also override these styles for individual Facebook feeds by setting options within the shortcode. For example, you can change the height of a specific Facebook feed like so: `[custom-facebook-feed height=500px]`.
215
-
216
- = The Custom Facebook Feed shortcode options aren't working =
217
-
218
- The most common causes of this are:
219
-
220
- 1) There's HTML tags within the [custom-facebook-feed] shortcode which are preventing it from working correctly
221
-
222
- If you copied and pasted the shortcode into the Visual editor on your WordPress page/post editor then it may have inadvertently included some HTML tags from the page that you copied it from. The easiest way to check this is to view the 'Text' view in your WordPress editor and see whether there are any stray HTML tags in the shortcode itself.
223
-
224
- 2) The shortcode includes curly single quote characters
225
226
- If your shortcode includes single quotes then check that they are the standard single quotes and not the curly kind.
227
228
- 3) Typo in the shortcode option
229
230
- Ensure that there aren't any spelling errors in the shortcode options that you're using and that the format is consistent with that demonstrated on the [Shortcode Options reference page](https://smashballoon.com/custom-facebook-feed/docs/shortcodes/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=shortcode "The shortcode options aren't working").
231
232
- = Facebook avatar pictures aren't showing up in my Facebook feed =
233
234
- The most common reason for this is that an add-on or extension you have installed in your web browser is blocking the pictures being loaded from Facebook. Try checking to see whether you have any add-ons or extensions installed in your browser and, if so, try disabling them to see whether that solves the problem and displays the pictures from Facebook.
235
236
- == Other Notes ==
237
238
- = At Smash Balloon we have two goals: =
239
240
- 1. Creating and maintaining the most useful, functional, customizable, robust and down-right awesomist Facebook feed plugin your website has ever seen.
241
- 2. To provide the quickest, friendliest and most mind-blowingly amazing product support you have ever experienced.
242
243
== Screenshots ==
244
245
- 1. By default the Facebook feed inherits your theme's default styles and the Facebook feed is completely responsive
246
2. Completely customize the way your Facebook feed looks to perfectly match your site
247
- 3. Use custom CSS to customize every part of the Facebook feed
248
- 4. Display Facebook events in your Facebook feed
249
- 5. Configuring the Custom Facebook Feed plugin
250
- 6. General Facebook Feed options - Custom Facebook Feed Layout and Style page
251
- 7. Facebook Feed Typography options - Custom Facebook Feed Layout and Style page
252
- 8. Misc Facebook Feed options - Custom Facebook Feed Layout and Style page
253
- 9. It's super easy to display your Facebook feed in any page or post
254
255
== Changelog ==
256
= 2.14.1 =
257
* Fix: Some connection error notices not clearing automatically.
258
259
= 2.14 =
260
* New: Email alerts for critical Facebook feed issues. If there's an issue with a Facebook feed on your website which hasn't been resolved yet then you'll receive an email notification to let you know. This is sent once per week until the issue is resolved. These emails can be disabled by using the following setting: Facebook Feed > Customize > Misc > Feed Issue Email Report.
261
- * New: Admin notifications for critical Facebook feed issues. If there is an error with a Facebook feed, admins will see notices in the dashboard and on the front-end of the site along with instructions on how to resolve the issue. Front-end admin notifications can be disabled by using the following setting: Facebook Feed > Customize > Misc > Disable Admin Error Notice.
262
* New: Added a WordPress 'Site Health' integration. If there is a critical error with your feeds, it will now be flagged in the site health page.
263
* New: Added "About Us" page for those who would like to learn more about Smash Balloon and our other products. Go to Facebook Feed -> About Us in the dashboard.
264
@@ -268,140 +175,49 @@ The most common reason for this is that an add-on or extension you have installe
268
269
= 2.12.4 =
270
* Tested with upcoming WordPress 5.4 update.
271
- * Tweak: Updated Facebook API calls
272
* Fix: Minor bug fixes
273
274
= 2.12.3 =
275
- * Tweak: Added a text link in the Facebook Feed settings page footer to our new free [YouTube plugin](https://wordpress.org/plugins/feeds-for-youtube/)
276
- * Tweak: When reconnecting a Facebook account on the settings page, if there's an issue with the existing Facebook access token then it'll be automatically replaced.
277
- * Tweak: Added 'rel="noopener"' to all external links and added 'rel="noreferrer"' to all non-Facebook links. Thanks to Dev VIP for the suggestion.
278
- * Fix: Fixed an issue with some Facebook call-to-action link URLs when a link protocol wasn't included
279
* Fix: Fixed a JavaScript conflict with the [Forminator](https://wordpress.org/plugins/forminator/) plugin
280
- * Fix: Fixed duplicate Facebook post message displaying due to ellipsis HTML character
281
- * Fix: If a shared Facebook link post had no post text then the link title was used causing it to be displayed twice in the Facebook post
282
283
= 2.12.2 =
284
* Fix: Fixed a JavaScript error in the admin caused by the previous update. Apologies for any inconvenience.
285
286
= 2.12.1 =
287
- * Fix: Fixed an issue with Facebook post date timezones due to changes in the WordPress 5.3 update
288
- * Fix: Fixed a rare issue where a JavaScript error would occur in the WordPress admin if a Facebook account was manually connected and the Facebook Page ID used was the full URL
289
* Fix: Fixed a JavaScript error in the admin when using older web browsers
290
* Tweak: Improved the manual account connection process
291
* Tweak: Some minor UI tweaks to match the new WordPress 5.3 UI style
292
293
= 2.12 =
294
- * New: Added a backup cache so the Facebook feed will still display even if there's an error from the Facebook API.
295
- * New: You can now easily manage multiple Facebook page or group accounts on the Facebook Feed plugin settings page allowing you to easily add them to other Facebook feeds on your site. When you connect a Facebook page or group you will now see it listed in the "Connected Accounts" section. You can add it to the primary Facebook feed or to another Facebook feed by using the new `account` shortcode option.
296
- * Tweak: Added a filter which can be used to filter the Facebook API data when returned; `cff_filter_api_data`.
297
- * Tweak: Updated Facebook API error messages
298
- * Fix: Fixed an issue with some @tag links in Facebook post text due to a Facebook API change
299
- * Fix: Fixed a rare issue with ellipsis chracter symbols in Facebook shared link descriptions causing the entire link description not to be displayed
300
301
= 2.11.1 =
302
- * Tweak: Added the link source URL below the title for Facebook shared link posts
303
- * Fix: Some themes would prevent the Facebook "Share" link from working successfully
304
- * Fix: Fixed an issue with the "Feed Columns" setting not working if the minified versions of the Custom Facebook Feed plugin CSS/JavaScript files were being used
305
306
= 2.11 =
307
- * New: Added a "Feed Columns" setting to allow you to display your Facebook feed in multiple columns. This can be found under the "General" tab on the "Customize" page, or by using the `cols` and `colsmobile` shortcode settings.
308
- * New: Updated to use v4.0 of the Facebook API
309
310
= 2.10 =
311
- * New: Facebook Groups are making their long-awaited return to the Custom Facebook Feed plugin! Just click the 'Log in and get my Facebook Access Token' button on the Facebook Feed Settings page and select 'Facebook Group'. Follow the prompts to connect your Facebook Group and display your feed.
312
- * Fix: Fixed an issue where a lists of Facebook groups or pages wouldn't be displayed when retrieving a Facebook Access Token due to a server configuration issue
313
- * Fix: Photo icons weren't showing for Facebook album posts
314
- * Tweak: Now uses the Facebook `visitor_posts` endpoint to display visitor Facebook post feeds
315
-
316
- = 2.9.1 =
317
- * New: Added support for v3.3 of the Facebook API.
318
- * Fix: The Facebook Access Token selection area was being cut off on small screens when a lot of Facebook pages were listed.
319
-
320
- = 2.9 =
321
- * New: You can now select between a "Regular" or "Boxed" Facebook post style. Settings for this can be found at: `Facebook Feed > Customize > Style Posts > Post Item`. A Box Shadow setting has been added to the "Boxed" Facebook post style.
322
- * New: Added some settings to control the size and color of the Facebook shared link URLs and descriptions. These can be found at: `Facebook Feed > Customize > Style Posts > Shared Link Boxes`.
323
- * New: Improved the Facebook Access Token retrieval process to make it more intuitive.
324
- * Tweak: Facebook avatar images are now circular to match Facebook.
325
- * Tweak: Animated the social media icons when the Facebook "Share" button is clicked.
326
- * Tweak: Changed the way the Facebook Like Box loads to avoid a conflict with the Facebook Messenger widget. It no longer uses the Facebook JavaScript SDK.
327
- * Tweak: Changed the elements used for icons from `<i>` to `<span>` to aid accessibility.
328
- * Tweak: Removed the Google+ share option as the platform has been deprecated.
329
- * Tweak: Removed the social media share widgets from the footer of the admin so that they're only loaded when the "Share the plugin" button is clicked.
330
- * Fix: The Custom Facebook Feed plugin now uses the built-in WordPress HTTP API to get data from Facebook instead of making it's own cURL requests to the Facebook API.
331
- * Fix: Fixed an issue where the Facebook avatars of people posting to the Facebook page weren't being displayed. Individual Facebook API requests for avatars have now been removed and bundled into the main Facebook API request.
332
- * Fix: If the link to the Facebook profile of a visitor posting to your page is not available then remove the link from the Facebook avatar and author name.
333
- * Fix: Fixed an accessibility error caused by the Facebook share icons being empty links.
334
- * Fix: Removed the use of the ENT_HTML5 constant as it isn't supported in PHP 5.4.
335
- * Fix: Fixed a rare issue with Facebook tags in Facebook post stories when the locale was set to be Greek.
336
-
337
- = 2.8 =
338
- * New: Added support for Facebook Notes in timeline feeds. If your Facebook timeline feed contains a note then the Custom Facebook Feed plugin will now get the content from the note and display it within the Facebook post.
339
- * New: Facebook call-to-action buttons - such as "Learn More", "Shop Now", and "Message Facebook Page" - are now supported in your Facebook posts. These text strings can be translated using the settings at: Facebook Feed > Customize > Custom Text/Translate
340
- * New: Added a setting that you can enable if you are displaying Facebook posts from a restricted (non-public) Facebook page. This will allow the Facebook page avatar to be displayed, and is located at: Facebook Feed > Customize > Misc > Misc Settings > Is Facebook Page restricted?
341
- * New: If a Facebook visitor posts to your Facebook page then their avatar will now be displayed and cached for 6 months. To clear the cache of these Facebook avatar images use the button located at: Facebook Feed > Customize > Misc > Misc Settings > Clear Avatar Cache
342
- * Tweak: The Timezone setting can now be set in the Custom Facebook Feed shortcode. Eg: `timezone="America/Los_Angeles"`
343
- * Tweak: Minor UI changes to the Facebook Feed admin pages
344
- * Tweak: Reduced some of the Facebook data in the System Info
345
- * Fix: If you backdate a Facebook post it will now be ordered correctly in your Facebook feed
346
- * Fix: Fixed a theme conflict related to the Color Picker in the Facebook Feed admin section
347
- * Verified compatibility with WordPress 5.0 and Gutenburg
348
-
349
- = 2.7.2 =
350
- * **Important:** If you are displaying a Facebook feed from a Facebook page which you are *not* an admin of then it is advised that you obtain a new Facebook Access Token in the plugin using the "Log in and get my Access Token" button. This will switch you from using the "SlickRemix" app to using our own "Smash Balloon" Facebook app which was recently approved by Facebook, and will prevent you from experiencing any potential interuptions in your Facebook feeds going forward. This will be the final time this is required.
351
- * Fix: Fixed a rare issue caused by some themes including the JavaScript file incorrectly
352
-
353
- = 2.7.1 =
354
- * Tweak: Made some adjustments to the Facebook Access Token login process
355
-
356
- = 2.7 =
357
- * New: Now easily get your own Facebook Access Token to avoid any Facebook connection issues. Simply click the blue Facebook "Log in and get my Facebook Access Token" button on the Custom Facebook Feed settings page and connect your Facebook account to get your token. The Facebook Access Token will work to get Facebook posts from ANY Facebook page. Thanks to our friends at SlickRemix for powering our new login and getting the Custom Facebook Feed plugin back up and running again!
358
- * Tweak: Removed the minimum caching time if you're using your own Facebook Page Access Token
359
-
360
- = 2.6.4 =
361
- * **Important:** If you are displaying Facebook posts from a Facebook page that **you are an admin of** then it is now highly recommended that you retrieve your own Facebook Access Token for that Facebook page to avoid any Facebook API rate limit errors. Simply follow these [step-by-step](https://smashballoon.com/custom-facebook-feed/page-token/?utm_campaign=facebook-free-readme&utm_source=changelog&utm_medium=limits) instructions to obtain one.
362
-
363
- = 2.6.3 =
364
- * Fix: Fixed an issue where Facebook API errors were being cached
365
-
366
- = 2.6.2 =
367
- * Fix: Replaced all HTTP links in the Facebook feed with HTTPS
368
- * Fix: Fixed a rare issue which affected the layout of other Facebook widgets
369
- * Fix: Automatically remove slashes at the end of the Facebook Page ID as it caused an error
370
- * Fix: The API response test in the System Info now only tests with your Facebook token if you have the "Use my own Facebook Access Token" setting enabled
371
- * Fix: Fixed an issue which caused an occasional Facebook API rate limit error
372
-
373
- = 2.6.1 =
374
- * Fix: Removed an unnecessary Facebook API call
375
- * Fix: Removed a PHP notice which was displayed under rare circumstances
376
- * Fix: Minor Facebook bug fixes
377
-
378
- = 2.6 =
379
- * Fix: Fixed an issue connecting to the Facebook API caused by a recent Facebook platform change
380
- * Tweak: Increased the minimum caching time to be 15 minutes to reduce Facebook API requests
381
-
382
- = 2.5.2 =
383
- * Important: Due to sudden changes in the Facebook API it is no longer possible to display Facebook posts from a Facebook Group. Please [see here](https://smashballoon.com/facebook-api-changes-april-4-2018/) for more information. We apologize for any frustration or inconvenience this has caused.
384
- * Removed: Due to Facebook API restrictions, it is no longer possible to display information about a Facebook event when it is posted or shared to your Facebook Page timeline.
385
-
386
- = 2.5.1 =
387
- * Fix: Prevented a PHP notice which would be displayed under rare circumstances in the Facebook feed
388
- * Fix: Replaced a function due to a deprecation in PHP 7.2
389
-
390
- = 2.5 =
391
- * New: Added the Facebook post story as part of the page/author name at the top of the Facebook post
392
- * New: Added an option to use minified versions of the plugin CSS and JavaScript files: `Facebook Feed > Customize > Misc > Misc Settings > Minify CSS and JavaScript files`
393
- * New: Added support for clearing the cache of major caching plugins when the Facebook feed cache is cleared. You can enable this by setting the following setting to be "Yes": `Facebook Feed > Customize > Misc > Misc Settings > Force cache to clear on interval`
394
- * Tweak: Improved the text truncation so that it applies to both the Facebook post text and Facebook description as one block of text and accounts for HTML link tags
395
- * Tweak: Added an "Auto" option to the Facebook Post Limit setting where it will automatically adjust the post limit based on the number of Facebook posts you choose to display in your Facebook feed
396
- * Tweak: Reorganized the Custom Facebook Feed settings pages to be more intuitive
397
- * Tweak: Added aria-hidden=true to icons to help improve accessibility
398
- * Tweak: The icon font stylesheet handle has been renamed so it will only be loaded once if another of our social media plugins is installed
399
- * Tweak: Facebook error messages are now only shown to admins
400
- * Tweak: Added a setting to workaround a theme issue that affects the shortening of the Facebook post text. If you're experiencing an issue with the shortening of Facebook post text then you can enable the following setting: `Facebook Feed > Customize > Misc > Misc Settings > Fix Facebook text shortening issue`
401
- * Fix: Included a fallback in case the Facebook author name and avatar aren't available in visitor Facebook posts
402
- * Fix: Fixed an issue with apostrophes in the Facebook feed header not being escaped correctly
403
- * Fix: Fixed an issue with the Facebook icons when Font Awesome 5 was added to a site
404
- * Fix: Added support for the @[ID:page-name] Facebook tagging format
405
- * Fix: The Facebook post description is now able to be displayed even if the Facebook post text is hidden
406
407
[See changelog for all versions](https://plugins.svn.wordpress.org/custom-facebook-feed/trunk/changelog.txt).
1
+ === Social Post Feed - Smash Balloon ===
2
+ Contributors: smashballoon, craig-at-smash-balloon
3
+ Tags: Facebook, Facebook feed, Facebook posts, Facebook group, Facebook page, Facebook wall
4
Requires at least: 3.0
5
Requires PHP: 5.2
6
Tested up to: 5.4
7
+ Stable tag: 2.15
8
License: GPLv2 or later
9
License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
11
+ Formerly "Custom Facebook Feed". Display completely customizable Facebook feeds of any public Facebook page or Group.
12
13
== Description ==
14
15
+ Display Facebook posts on your WordPress site. **Completely customizable**, **responsive** and **search engine crawlable** Facebook feeds. Display **unlimited feeds** from **any public Facebook page** or your **Facebook Group**, and completely match the look and feel of your site with tons of customization options!
16
17
+ ### Facebook Feed Features
18
+ **Super Simple to Set Up**
19
+ One of our main priorities has always been to make our Facebook plugin as easy as possible to setup and use. Get up and running in less less than 1 minute with our signature quick setup - no Facebook Developer App required.
20
21
+ **Display Feeds from ANY Facebook Page or Your Facebook Group**
22
+ Use the plugin to display feeds from any public page - even pages you aren't an admin of - or from any group that you are an admin of.
23
24
+ **Completely Customizable**
25
+ By default the feed will adopt the styles of your WordPress theme, but your feeds can be completely customized to look however you like - with tons of options to customize every part of your posts and feed.
26
27
+ **SEO Friendly**
28
+ The Facebook feed content is crawlable by search engines adding SEO value to your site, while other Facebook plugins embed the feed using iframes which are not crawlable.
29
+
30
+ **Responsive and Mobile Optimized**
31
+ Feed layouts look great on any screen size and in any container width.
32
+
33
+ **Unlimited Feeds from Unlimited Different Facebook Pages**
34
+ We don't limit how many feeds you can display on your site. Just use the shortcode to embed as many feeds as you like into pages, posts or widgets anywhere on your site.
35
36
+ **Built for Speed**
37
+ Built-in caching means that your Facebook feeds load lightning fast. Set your own caching time - check for new posts every few seconds, minutes, hours or days. You decide.
38
+
39
+ **Like Box Widget and Visual Header**
40
+ Include the official Facebook Like Box widget at the top or bottom of your feed and display a beautiful visual header with your page or group cover photo, profile picture, bio, and number of likes.
41
+
42
+ **So Much More**
43
+ Show and hide certain parts of each post, choose whose posts to show in the feed, customize colors, font sizes and styles, the number of posts to display, set max text lengths, translate text, custom CSS, and much, much more.
44
45
### Pro Version (Custom Facebook Feed Pro)
46
47
+ This free plugin allows you to display text and links from Facebook posts. In order to maintain the plugin on an ongoing basis, and to provide quick and effective support for free, we offer a Pro version of the plugin which allows you to display photos and videos, the number of likes, shares, reactions and comments for posts in each Facebook feed, choose from multiple layout options, filter posts by type or #hashtag/string, load more posts into your feed, and more. [Click here](https://smashballoon.com/differences-between-the-free-version-and-pro-version-of-the-custom-facebook-feed-plugin/ "Differences between free and Pro version of Custom Facebook Feed plugin") for a full list of all differences between the free and Pro versions.
48
49
+ * [Find out more about the Pro version](https://smashballoon.com/custom-facebook-feed/?utm_campaign=facebook-free-readme&utm_source=proversion&utm_medium=findout "Pro Version")
50
+ * [Try out the Pro demo](https://smashballoon.com/custom-facebook-feed/demo/?utm_campaign=facebook-free-readme&utm_source=proversion&utm_medium=demo "Pro Demo").
51
52
+ ### Benefits of Displaying a Facebook Feed on Your Website
53
54
* **Increase social engagement** between you and your users, customers, or fans
55
+ * **Save time** by using the plugin to generate dynamic, search engine crawlable content on your website
56
* **Get more likes** by displaying your Facebook content directly on your site
57
+ * **Improve your SEO** as all of that quality keyword-rich Facebook content from posts and comments is directly embedded into your website
58
* Display your Facebook content your way to perfectly match your website's style
59
* **No Coding Required** - choose from tons of built-in customization options to create a truly unique feed of your Facebook content.
60
+ * The plugin is **updated regularly** with new features, bug-fixes and API changes
61
* Support is quick and effective
62
* We're dedicated to providing the **most customizable**, **robust** and **well supported** Facebook feed plugin in the world!
63
64
+ ### How to use the plugin
65
66
+ Once you've installed the plugin there are only a few steps to get up and running:
67
68
+ 1) Use the button on the 'Facebook Feed' settings page to log into your Facebook account and authorize the plugin.
69
+ 2) Save the plugin settings and add the `[custom-facebook-feed]` shortcode to any page, post, or widget where you want the feed to be displayed.
70
71
+ That's it! You can then customize the feed as needed using the settings on the Customize page.
72
73
+ For full step-by-step setup directions with screenshots, see [here](https://smashballoon.com/custom-facebook-feed/docs/free/?utm_campaign=facebook-free-readme&utm_source=howto&utm_medium=setup "Free Setup Doc").
74
75
### Requesting support
76
77
+ Customer support is a huge deal to us. We pride ourselves on always providing quick, effective, and courteous support to all of our users. If you're having an issue using the plugin then just let us know and we'll be there to help as soon as possible. You can either open a ticket on the support forum on [WordPress.org](https://wordpress.org/support/plugin/custom-facebook-feed/ "Support forum"), or directly on [our website](https://smashballoon.com/custom-facebook-feed/support/ "Support form"). We also have a large collection of help documentation and FAQs [on our website](https://smashballoon.com/custom-facebook-feed/faq/ "Support FAQs") for all common issues related to plugin.
78
79
### Who's behind this plugin?
80
81
We're Smash Balloon; a fun-loving WordPress plugin development company birthed into existence in early 2013. We specialize in creating social media plugins that are not only intuitive and simple to use, but also designed to integrate seamlessly into your website and allow you to display your social media content in powerful and unique ways. Over 1 million awesome people have decided to actively use our free plugins, which is an incredible honor that we don't take lightly. This compels us to try to provide the quickest and most effective customer support that we can, blowing users away with the best customer service they've ever experienced.
82
83
+ To find out more about the team, see [here](https://smashballoon.com/about/?utm_campaign=facebook-free-readme&utm_source=who&utm_medium=about "Team Smash Balloon"), or check out our other free plugins for [Instagram](https://wordpress.org/plugins/instagram-feed "Instagram Feed free plugin"), [Twitter](https://wordpress.org/plugins/custom-twitter-feeds/ "Custom Twitter Feeds free plugin"), and [YouTube](https://wordpress.org/plugins/feeds-for-youtube/ "Feeds for YouTube free plugin").
84
85
== Installation ==
86
87
+ 1. Install the plugin either via the WordPress plugin directory, or by uploading the files to your web server (in the `/wp-content/plugins/` directory).
88
2. Activate the plugin through the 'Plugins' menu in WordPress.
89
3. Navigate to the 'Facebook Feed' settings page to configure your feed.
90
+ 4. Add the `[custom-facebook-feed]` shortcode to your page, post or widget to display your feed.
91
5. You can display multiple feeds of different Facebook pages by specifying a Page ID directly in the shortcode: `[custom-facebook-feed id=smashballoon num=5]`.
92
93
== Frequently Asked Questions ==
96
97
= How do I find the Page ID of my Facebook page? =
98
99
+ If you have a **page** with a URL like this: `https://www.facebook.com/smashballoon` then the Page ID is just `smashballoon`. If your page URL is structured like this: `https://www.facebook.com/pages/smashballoon/123654123654123` then the Page ID is actually the number at the end, so in this case `123654123654123`.
100
101
Copy and paste the ID into the [Pro demo](https://smashballoon.com/custom-facebook-feed/demo/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=demoid) to test it.
102
103
+ = Are there any limitations on which Facebook page or Facebook group feeds I can display? =
104
105
+ The feed you're trying to display has to be from a publicly accessible Facebook page or Facebook group. This means that you can't display the feed from your own personal profile. This is to do with FB privacy policies. You can't display a non-public Facebook feed publicly.
106
107
+ If your Facebook page has any restrictions on it (age, for example) then it means that people have to be signed into FB in order to view your page. This isn't desirable for most FB pages as it means that it isn't accessible by people who don't have a FB account and that your Facebook page can't be crawled and indexed by search engines.
108
109
+ An easy way to determine whether your Facebook page is set to public is to sign out of your FB account and try to visit your page. If Facebook forces you to sign in to view your page then it isn't public. You can change your page to public in your Facebook page settings simply by removing any age or location restrictions you have on it ([screenshot](https://smashballoon.com/wp-content/uploads/2013/06/facebook-page-restrictions.png)), which will then allow the plugin to access and display your feed.
110
111
+ = Can I display feeds from multiple pages? =
112
113
+ You can set your default Facebook Page ID on the plugin settings page within the WordPress admin, you can then define different page IDs in the shortcodes you use to show multiple feeds from different pages. Just use the id option in your shortcode like so: [custom-facebook-feed id=another_page_id]. You can use as many shortcodes as you like with as many different IDs as you like.
114
115
+ = Can I display feeds from a Facebook Group? =
116
117
+ Yep! First, authorize the plugin by using the big blue button on the plugin settings page and then select your Facebook group. You must be a member of the group and an admin of the Facebook group must have installed our app in the group settings. Directions for this are provided when you authorize the plugin via the plugin settings page.
118
119
+ = Can I display the feed from a personal profile? =
120
121
+ Due to FB's privacy policy you're not able to use the plugin to display all of your posts from a personal profile, only from a public page, as posts from a personal profile are protected for privacy reasons. You may have limited success in displaying certain posts from a personal profile but most posts are not able to be displayed.
122
123
+ If you're using the profile to represent a business, organization, product, public figure or the like, then we'd advise converting your profile to a page per [FB's recommendation](http://www.facebook.com/help/175644189234902/), as there are many advantages to using pages over profiles.
124
125
+ Once you've done so, the plugin will be able to retrieve and display all of your posts.
126
127
+ = Can I show photos and videos in my feed? =
128
129
+ This free plugin only allows you to display text from your posts. To display photos and videos in your feed you would need to upgrade to the Pro version of the plugin. Try out a demo of the Pro version on our [website](https://smashballoon.com/custom-facebook-feed/demo/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=media "Demo"), and find out more about the Pro version [here](https://smashballoon.com/custom-facebook-feed/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=pro "Pro"). [Click here](https://smashballoon.com/differences-between-the-free-version-and-pro-version-of-the-custom-facebook-feed-plugin/ "Differences between free and Pro version") for a full list of all differences between the free version and Pro version.
130
131
+ = Can I show the comments, shares and likes associated with each post? =
132
133
+ This is a feature of the [Pro version of the plugin](https://smashballoon.com/custom-facebook-feed/?utm_campaign=facebook-free-readme&utm_source=faq&utm_medium=comments "Pro Version"). To display comments, shares and likes you would need to upgrade from the free version to the Pro version.
134
135
+ = Is the content of my feed crawlable by search engines? =
136
137
+ It sure is. Unlike other Facebook plugins which use iframes to embed your feed into your page once it's loaded, our plugin uses PHP to embed your Facebook feed content directly into your page. This adds dynamic, search engine crawlable content to your site.
138
139
+ = How do I embed the feed directly into a WordPress page template? =
140
141
+ You can embed your feed directly into a template file by using the WordPress [do_shortcode](http://codex.wordpress.org/Function_Reference/do_shortcode "WordPress.org do_shortcode reference") function: `<?php echo do_shortcode('[custom-facebook-feed]'); ?>`.
142
143
== Screenshots ==
144
145
+ 1. By default the Facebook feed inherits your theme's default styles and the feed is completely responsive
146
2. Completely customize the way your Facebook feed looks to perfectly match your site
147
+ 3. Use custom CSS to customize every part of the feed
148
+ 4. Display Facebook events in your feed
149
+ 5. Configuring the plugin
150
+ 6. General options - Layout and Style page
151
+ 7. Typography options - Layout and Style page
152
+ 8. Misc options - Layout and Style page
153
+ 9. It's super easy to display your feed in any page or post
154
155
== Changelog ==
156
+ = 2.15 =
157
+ * New: Added a new visual header option which displays the cover photo, avatar, page name, bio, and number of likes from your Facebook page at the top of your feeds. To enable the header, go to Facebook Feed > Customize > General > Header > Header Type > Visual.
158
+ * New: To help us improve the plugin we've added the ability to opt-in to usage tracking so that we can understand what features and settings are being used, and which features matter to you the most. This is disabled by default and will only be enabled if you explictly choose to opt in. If opted in, the plugin will send a report in the background once per week with your plugin settings and basic information about your website environment. No personal or sensitive data is collected (such as email addresses, Instagram account information, license keys, etc). To enable or disable usage tracking at a later date use the setting at: Instagram Feed > Customize > Advanced > Misc > Enable Usage Tracking. See [here](https://smashballoon.com/custom-facebook-feed/docs/usage-tracking/) for more information.
159
+ * New: Added a setting to display a different number of posts on mobile devices vs desktop. While on the configure tab, check the box "Show different number for mobile" to reveal the setting.
160
+ * New: Added capability "manage_custom_facebook_feed_options". Users with this capability can make changes to Facebook Feed settings and view admin only messages.
161
+ * New: Added a PHP filter "cff_post_text" to change the post text before outputting it in the feed HTML.
162
+
163
= 2.14.1 =
164
* Fix: Some connection error notices not clearing automatically.
165
166
= 2.14 =
167
* New: Email alerts for critical Facebook feed issues. If there's an issue with a Facebook feed on your website which hasn't been resolved yet then you'll receive an email notification to let you know. This is sent once per week until the issue is resolved. These emails can be disabled by using the following setting: Facebook Feed > Customize > Misc > Feed Issue Email Report.
168
+ * New: Admin notifications for critical Facebook feed issues. If there is an error with a feed, admins will see notices in the dashboard and on the front-end of the site along with instructions on how to resolve the issue. Front-end admin notifications can be disabled by using the following setting: Facebook Feed > Customize > Misc > Disable Admin Error Notice.
169
* New: Added a WordPress 'Site Health' integration. If there is a critical error with your feeds, it will now be flagged in the site health page.
170
* New: Added "About Us" page for those who would like to learn more about Smash Balloon and our other products. Go to Facebook Feed -> About Us in the dashboard.
171
175
176
= 2.12.4 =
177
* Tested with upcoming WordPress 5.4 update.
178
+ * Tweak: Updated API calls
179
* Fix: Minor bug fixes
180
181
= 2.12.3 =
182
+ * Tweak: Added a text link in the settings page footer to our new free [YouTube plugin](https://wordpress.org/plugins/feeds-for-youtube/)
183
+ * Tweak: When reconnecting an account on the settings page, if there's an issue with the existing access token then it'll be automatically replaced.
184
+ * Tweak: Added 'rel="noopener"' to all external links and added 'rel="noreferrer"' to all non-FB links. Thanks to Dev VIP for the suggestion.
185
+ * Fix: Fixed an issue with some call-to-action link URLs when a link protocol wasn't included
186
* Fix: Fixed a JavaScript conflict with the [Forminator](https://wordpress.org/plugins/forminator/) plugin
187
+ * Fix: Fixed duplicate post message displaying due to ellipsis HTML character
188
+ * Fix: If a shared link post had no post text then the link title was used causing it to be displayed twice in the post
189
190
= 2.12.2 =
191
* Fix: Fixed a JavaScript error in the admin caused by the previous update. Apologies for any inconvenience.
192
193
= 2.12.1 =
194
+ * Fix: Fixed an issue with post date timezones due to changes in the WordPress 5.3 update
195
+ * Fix: Fixed a rare issue where a JavaScript error would occur in the WordPress admin if an account was manually connected and the Page ID used was the full URL
196
* Fix: Fixed a JavaScript error in the admin when using older web browsers
197
* Tweak: Improved the manual account connection process
198
* Tweak: Some minor UI tweaks to match the new WordPress 5.3 UI style
199
200
= 2.12 =
201
+ * New: Added a backup cache so the feed will still display even if there's an error from the API.
202
+ * New: You can now easily manage multiple Facebook page or group accounts on the plugin settings page allowing you to easily add them to other feeds on your site. When you connect a page or group you will now see it listed in the "Connected Accounts" section. You can add it to the primary feed or to another feed by using the new `account` shortcode option.
203
+ * Tweak: Added a filter which can be used to filter the API data when returned; `cff_filter_api_data`.
204
+ * Tweak: Updated API error messages
205
+ * Fix: Fixed an issue with some @tag links in post text due to a API change
206
+ * Fix: Fixed a rare issue with ellipsis chracter symbols in shared link descriptions causing the entire link description not to be displayed
207
208
= 2.11.1 =
209
+ * Tweak: Added the link source URL below the title for shared link posts
210
+ * Fix: Some themes would prevent the "Share" link from working successfully
211
+ * Fix: Fixed an issue with the "Feed Columns" setting not working if the minified versions of the plugin CSS/JavaScript files were being used
212
213
= 2.11 =
214
+ * New: Added a "Feed Columns" setting to allow you to display your feed in multiple columns. This can be found under the "General" tab on the "Customize" page, or by using the `cols` and `colsmobile` shortcode settings.
215
+ * New: Updated to use v4.0 of the API
216
217
= 2.10 =
218
+ * New: Facebook Groups are making their long-awaited return to the plugin! Just click the 'Log in and get my Access Token' button on the plugin's Settings page and select 'Facebook Group'. Follow the prompts to connect your Group and display your feed.
219
+ * Fix: Fixed an issue where a lists of groups or pages wouldn't be displayed when retrieving an Access Token due to a server configuration issue
220
+ * Fix: Photo icons weren't showing for album posts
221
+ * Tweak: Now uses the `visitor_posts` endpoint to display visitor post feeds
222
223
[See changelog for all versions](https://plugins.svn.wordpress.org/custom-facebook-feed/trunk/changelog.txt).
admin/PluginSilentUpgrader.php CHANGED
@@ -1,576 +1,576 @@
1
- <?php
2
-
3
- namespace CFF\Helpers;
4
-
5
- use WP_Error;
6
- use WP_Upgrader;
7
- use WP_Filesystem_Base;
8
-
9
- /** \WP_Upgrader class */
10
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
11
-
12
- /** \Plugin_Upgrader class */
13
- require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
14
-
15
- /**
16
- * In WP 5.3 a PHP 5.6 splat operator (...$args) was added to \WP_Upgrader_Skin::feedback().
17
- * We need to remove all calls to *Skin::feedback() method, as we can't override it in own Skins
18
- * without breaking support for PHP 5.3-5.5.
19
- *
20
- * @internal Please do not use this class outside of core WPForms development. May be removed at any time.
21
- *
22
- * @since 1.5.6.1
23
- */
24
- class PluginSilentUpgrader extends \Plugin_Upgrader {
25
-
26
- /**
27
- * Run an upgrade/installation.
28
- *
29
- * Attempts to download the package (if it is not a local file), unpack it, and
30
- * install it in the destination folder.
31
- *
32
- * @since 1.5.6.1
33
- *
34
- * @param array $options {
35
- * Array or string of arguments for upgrading/installing a package.
36
- *
37
- * @type string $package The full path or URI of the package to install.
38
- * Default empty.
39
- * @type string $destination The full path to the destination folder.
40
- * Default empty.
41
- * @type bool $clear_destination Whether to delete any files already in the
42
- * destination folder. Default false.
43
- * @type bool $clear_working Whether to delete the files form the working
44
- * directory after copying to the destination.
45
- * Default false.
46
- * @type bool $abort_if_destination_exists Whether to abort the installation if the destination
47
- * folder already exists. When true, `$clear_destination`
48
- * should be false. Default true.
49
- * @type bool $is_multi Whether this run is one of multiple upgrade/installation
50
- * actions being performed in bulk. When true, the skin
51
- * WP_Upgrader::header() and WP_Upgrader::footer()
52
- * aren't called. Default false.
53
- * @type array $hook_extra Extra arguments to pass to the filter hooks called by
54
- * WP_Upgrader::run().
55
- * }
56
- * @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error,
57
- * or false if unable to connect to the filesystem.
58
- */
59
- public function run( $options ) {
60
-
61
- $defaults = array(
62
- 'package' => '', // Please always pass this.
63
- 'destination' => '', // And this
64
- 'clear_destination' => false,
65
- 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please
66
- 'clear_working' => true,
67
- 'is_multi' => false,
68
- 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
69
- );
70
-
71
- $options = wp_parse_args( $options, $defaults );
72
-
73
- /**
74
- * Filters the package options before running an update.
75
- *
76
- * See also {@see 'upgrader_process_complete'}.
77
- *
78
- * @since 4.3.0
79
- *
80
- * @param array $options {
81
- * Options used by the upgrader.
82
- *
83
- * @type string $package Package for update.
84
- * @type string $destination Update location.
85
- * @type bool $clear_destination Clear the destination resource.
86
- * @type bool $clear_working Clear the working resource.
87
- * @type bool $abort_if_destination_exists Abort if the Destination directory exists.
88
- * @type bool $is_multi Whether the upgrader is running multiple times.
89
- * @type array $hook_extra {
90
- * Extra hook arguments.
91
- *
92
- * @type string $action Type of action. Default 'update'.
93
- * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
94
- * @type bool $bulk Whether the update process is a bulk update. Default true.
95
- * @type string $plugin Path to the plugin file relative to the plugins directory.
96
- * @type string $theme The stylesheet or template name of the theme.
97
- * @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme',
98
- * or 'core'.
99
- * @type object $language_update The language pack update offer.
100
- * }
101
- * }
102
- */
103
- $options = apply_filters( 'upgrader_package_options', $options );
104
-
105
- if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times
106
- $this->skin->header();
107
- }
108
-
109
- // Connect to the Filesystem first.
110
- $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) );
111
- // Mainly for non-connected filesystem.
112
- if ( ! $res ) {
113
- if ( ! $options['is_multi'] ) {
114
- $this->skin->footer();
115
- }
116
- return false;
117
- }
118
-
119
- $this->skin->before();
120
-
121
- if ( is_wp_error( $res ) ) {
122
- $this->skin->error( $res );
123
- $this->skin->after();
124
- if ( ! $options['is_multi'] ) {
125
- $this->skin->footer();
126
- }
127
- return $res;
128
- }
129
-
130
- /*
131
- * Download the package (Note, This just returns the filename
132
- * of the file if the package is a local file)
133
- */
134
- $download = $this->download_package( $options['package'], true );
135
-
136
- // Allow for signature soft-fail.
137
- // WARNING: This may be removed in the future.
138
- if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) {
139
-
140
- // Don't output the 'no signature could be found' failure message for now.
141
- if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) {
142
- // Outout the failure error as a normal feedback, and not as an error:
143
- //$this->skin->feedback( $download->get_error_message() );
144
-
145
- // Report this failure back to WordPress.org for debugging purposes.
146
- wp_version_check(
147
- array(
148
- 'signature_failure_code' => $download->get_error_code(),
149
- 'signature_failure_data' => $download->get_error_data(),
150
- )
151
- );
152
- }
153
-
154
- // Pretend this error didn't happen.
155
- $download = $download->get_error_data( 'softfail-filename' );
156
- }
157
-
158
- if ( is_wp_error( $download ) ) {
159
- $this->skin->error( $download );
160
- $this->skin->after();
161
- if ( ! $options['is_multi'] ) {
162
- $this->skin->footer();
163
- }
164
- return $download;
165
- }
166
-
167
- $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file
168
-
169
- // Unzips the file into a temporary directory.
170
- $working_dir = $this->unpack_package( $download, $delete_package );
171
- if ( is_wp_error( $working_dir ) ) {
172
- $this->skin->error( $working_dir );
173
- $this->skin->after();
174
- if ( ! $options['is_multi'] ) {
175
- $this->skin->footer();
176
- }
177
- return $working_dir;
178
- }
179
-
180
- // With the given options, this installs it to the destination directory.
181
- $result = $this->install_package(
182
- array(
183
- 'source' => $working_dir,
184
- 'destination' => $options['destination'],
185
- 'clear_destination' => $options['clear_destination'],
186
- 'abort_if_destination_exists' => $options['abort_if_destination_exists'],
187
- 'clear_working' => $options['clear_working'],
188
- 'hook_extra' => $options['hook_extra'],
189
- )
190
- );
191
-
192
- $this->skin->set_result( $result );
193
- if ( is_wp_error( $result ) ) {
194
- $this->skin->error( $result );
195
- //$this->skin->feedback( 'process_failed' );
196
- } else {
197
- // Installation succeeded.
198
- //$this->skin->feedback( 'process_success' );
199
- }
200
-
201
- $this->skin->after();
202
-
203
- if ( ! $options['is_multi'] ) {
204
-
205
- /**
206
- * Fires when the upgrader process is complete.
207
- *
208
- * See also {@see 'upgrader_package_options'}.
209
- *
210
- * @since 3.6.0
211
- * @since 3.7.0 Added to WP_Upgrader::run().
212
- * @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`.
213
- *
214
- * @param WP_Upgrader $this WP_Upgrader instance. In other contexts, $this, might be a
215
- * Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
216
- * @param array $hook_extra {
217
- * Array of bulk item update data.
218
- *
219
- * @type string $action Type of action. Default 'update'.
220
- * @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
221
- * @type bool $bulk Whether the update process is a bulk update. Default true.
222
- * @type array $plugins Array of the basename paths of the plugins' main files.
223
- * @type array $themes The theme slugs.
224
- * @type array $translations {
225
- * Array of translations update data.
226
- *
227
- * @type string $language The locale the translation is for.
228
- * @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'.
229
- * @type string $slug Text domain the translation is for. The slug of a theme/plugin or
230
- * 'default' for core translations.
231
- * @type string $version The version of a theme, plugin, or core.
232
- * }
233
- * }
234
- */
235
- do_action( 'upgrader_process_complete', $this, $options['hook_extra'] );
236
-
237
- $this->skin->footer();
238
- }
239
-
240
- return $result;
241
- }
242
-
243
- /**
244
- * Toggle maintenance mode for the site.
245
- *
246
- * Create/delete the maintenance file to enable/disable maintenance mode.
247
- *
248
- * @since 2.8.0
249
- *
250
- * @global WP_Filesystem_Base $wp_filesystem Subclass
251
- *
252
- * @param bool $enable True to enable maintenance mode, false to disable.
253
- */
254
- public function maintenance_mode( $enable = false ) {
255
- global $wp_filesystem;
256
- $file = $wp_filesystem->abspath() . '.maintenance';
257
- if ( $enable ) {
258
- //$this->skin->feedback( 'maintenance_start' );
259
- // Create maintenance file to signal that we are upgrading
260
- $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
261
- $wp_filesystem->delete( $file );
262
- $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );
263
- } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) {
264
- //$this->skin->feedback( 'maintenance_end' );
265
- $wp_filesystem->delete( $file );
266
- }
267
- }
268
-
269
- /**
270
- * Download a package.
271
- *
272
- * @since 2.8.0
273
- *
274
- * @param string $package The URI of the package. If this is the full path to an
275
- * existing local file, it will be returned untouched.
276
- * @param bool $check_signatures Whether to validate file signatures. Default false.
277
- * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object.
278
- */
279
- public function download_package( $package, $check_signatures = false ) {
280
-
281
- /**
282
- * Filters whether to return the package.
283
- *
284
- * @since 3.7.0
285
- *
286
- * @param bool $reply Whether to bail without returning the package.
287
- * Default false.
288
- * @param string $package The package file name.
289
- * @param WP_Upgrader $this The WP_Upgrader instance.
290
- */
291
- $reply = apply_filters( 'upgrader_pre_download', false, $package, $this );
292
- if ( false !== $reply ) {
293
- return $reply;
294
- }
295
-
296
- if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote?
297
- return $package; //must be a local file..
298
- }
299
-
300
- if ( empty( $package ) ) {
301
- return new WP_Error( 'no_package', $this->strings['no_package'] );
302
- }
303
-
304
- //$this->skin->feedback( 'downloading_package', $package );
305
-
306
- $download_file = download_url( $package, 300, $check_signatures );
307
-
308
- if ( is_wp_error( $download_file ) && ! $download_file->get_error_data( 'softfail-filename' ) ) {
309
- return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() );
310
- }
311
-
312
- return $download_file;
313
- }
314
-
315
- /**
316
- * Unpack a compressed package file.
317
- *
318
- * @since 2.8.0
319
- *
320
- * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
321
- *
322
- * @param string $package Full path to the package file.
323
- * @param bool $delete_package Optional. Whether to delete the package file after attempting
324
- * to unpack it. Default true.
325
- * @return string|WP_Error The path to the unpacked contents, or a WP_Error on failure.
326
- */
327
- public function unpack_package( $package, $delete_package = true ) {
328
- global $wp_filesystem;
329
-
330
- //$this->skin->feedback( 'unpack_package' );
331
-
332
- $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
333
-
334
- //Clean up contents of upgrade directory beforehand.
335
- $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
336
- if ( ! empty( $upgrade_files ) ) {
337
- foreach ( $upgrade_files as $file ) {
338
- $wp_filesystem->delete( $upgrade_folder . $file['name'], true );
339
- }
340
- }
341
-
342
- // We need a working directory - Strip off any .tmp or .zip suffixes
343
- $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );
344
-
345
- // Clean up working directory
346
- if ( $wp_filesystem->is_dir( $working_dir ) ) {
347
- $wp_filesystem->delete( $working_dir, true );
348
- }
349
-
350
- // Unzip package to working directory
351
- $result = unzip_file( $package, $working_dir );
352
-
353
- // Once extracted, delete the package if required.
354
- if ( $delete_package ) {
355
- unlink( $package );
356
- }
357
-
358
- if ( is_wp_error( $result ) ) {
359
- $wp_filesystem->delete( $working_dir, true );
360
- if ( 'incompatible_archive' == $result->get_error_code() ) {
361
- return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );
362
- }
363
- return $result;
364
- }
365
-
366
- return $working_dir;
367
- }
368
-
369
- /**
370
- * Install a package.
371
- *
372
- * Copies the contents of a package form a source directory, and installs them in
373
- * a destination directory. Optionally removes the source. It can also optionally
374
- * clear out the destination folder if it already exists.
375
- *
376
- * @since 2.8.0
377
- *
378
- * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
379
- * @global array $wp_theme_directories
380
- *
381
- * @param array|string $args {
382
- * Optional. Array or string of arguments for installing a package. Default empty array.
383
- *
384
- * @type string $source Required path to the package source. Default empty.
385
- * @type string $destination Required path to a folder to install the package in.
386
- * Default empty.
387
- * @type bool $clear_destination Whether to delete any files already in the destination
388
- * folder. Default false.
389
- * @type bool $clear_working Whether to delete the files form the working directory
390
- * after copying to the destination. Default false.
391
- * @type bool $abort_if_destination_exists Whether to abort the installation if
392
- * the destination folder already exists. Default true.
393
- * @type array $hook_extra Extra arguments to pass to the filter hooks called by
394
- * WP_Upgrader::install_package(). Default empty array.
395
- * }
396
- *
397
- * @return array|WP_Error The result (also stored in `WP_Upgrader::$result`), or a WP_Error on failure.
398
- */
399
- public function install_package( $args = array() ) {
400
- global $wp_filesystem, $wp_theme_directories;
401
-
402
- $defaults = array(
403
- 'source' => '', // Please always pass this
404
- 'destination' => '', // and this
405
- 'clear_destination' => false,
406
- 'clear_working' => false,
407
- 'abort_if_destination_exists' => true,
408
- 'hook_extra' => array(),
409
- );
410
-
411
- $args = wp_parse_args( $args, $defaults );
412
-
413
- // These were previously extract()'d.
414
- $source = $args['source'];
415
- $destination = $args['destination'];
416
- $clear_destination = $args['clear_destination'];
417
-
418
- set_time_limit( 300 );
419
-
420
- if ( empty( $source ) || empty( $destination ) ) {
421
- return new WP_Error( 'bad_request', $this->strings['bad_request'] );
422
- }
423
- //$this->skin->feedback( 'installing_package' );
424
-
425
- /**
426
- * Filters the install response before the installation has started.
427
- *
428
- * Returning a truthy value, or one that could be evaluated as a WP_Error
429
- * will effectively short-circuit the installation, returning that value
430
- * instead.
431
- *
432
- * @since 2.8.0
433
- *
434
- * @param bool|WP_Error $response Response.
435
- * @param array $hook_extra Extra arguments passed to hooked filters.
436
- */
437
- $res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] );
438
-
439
- if ( is_wp_error( $res ) ) {
440
- return $res;
441
- }
442
-
443
- //Retain the Original source and destinations
444
- $remote_source = $args['source'];
445
- $local_destination = $destination;
446
-
447
- $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) );
448
- $remote_destination = $wp_filesystem->find_folder( $local_destination );
449
-
450
- //Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
451
- if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents.
452
- $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] );
453
- } elseif ( count( $source_files ) == 0 ) {
454
- return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files?
455
- } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename.
456
- $source = trailingslashit( $args['source'] );
457
- }
458
-
459
- /**
460
- * Filters the source file location for the upgrade package.
461
- *
462
- * @since 2.8.0
463
- * @since 4.4.0 The $hook_extra parameter became available.
464
- *
465
- * @param string $source File source location.
466
- * @param string $remote_source Remote file source location.
467
- * @param WP_Upgrader $this WP_Upgrader instance.
468
- * @param array $hook_extra Extra arguments passed to hooked filters.
469
- */
470
- $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] );
471
-
472
- if ( is_wp_error( $source ) ) {
473
- return $source;
474
- }
475
-
476
- // Has the source location changed? If so, we need a new source_files list.
477
- if ( $source !== $remote_source ) {
478
- $source_files = array_keys( $wp_filesystem->dirlist( $source ) );
479
- }
480
-
481
- /*
482
- * Protection against deleting files in any important base directories.
483
- * Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the
484
- * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
485
- * to copy the directory into the directory, whilst they pass the source
486
- * as the actual files to copy.
487
- */
488
- $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );
489
-
490
- if ( is_array( $wp_theme_directories ) ) {
491
- $protected_directories = array_merge( $protected_directories, $wp_theme_directories );
492
- }
493
-
494
- if ( in_array( $destination, $protected_directories ) ) {
495
- $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
496
- $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
497
- }
498
-
499
- if ( $clear_destination ) {
500
- // We're going to clear the destination if there's something there.
501
- //$this->skin->feedback( 'remove_old' );
502
-
503
- $removed = $this->clear_destination( $remote_destination );
504
-
505
- /**
506
- * Filters whether the upgrader cleared the destination.
507
- *
508
- * @since 2.8.0
509
- *
510
- * @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure
511
- * @param string $local_destination The local package destination.
512
- * @param string $remote_destination The remote package destination.
513
- * @param array $hook_extra Extra arguments passed to hooked filters.
514
- */
515
- $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
516
-
517
- if ( is_wp_error( $removed ) ) {
518
- return $removed;
519
- }
520
- } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) {
521
- //If we're not clearing the destination folder and something exists there already, Bail.
522
- //But first check to see if there are actually any files in the folder.
523
- $_files = $wp_filesystem->dirlist( $remote_destination );
524
- if ( ! empty( $_files ) ) {
525
- $wp_filesystem->delete( $remote_source, true ); //Clear out the source files.
526
- return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination );
527
- }
528
- }
529
-
530
- //Create destination if needed
531
- if ( ! $wp_filesystem->exists( $remote_destination ) ) {
532
- if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
533
- return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination );
534
- }
535
- }
536
- // Copy new version of item into place.
537
- $result = copy_dir( $source, $remote_destination );
538
- if ( is_wp_error( $result ) ) {
539
- if ( $args['clear_working'] ) {
540
- $wp_filesystem->delete( $remote_source, true );
541
- }
542
- return $result;
543
- }
544
-
545
- //Clear the Working folder?
546
- if ( $args['clear_working'] ) {
547
- $wp_filesystem->delete( $remote_source, true );
548
- }
549
-
550
- $destination_name = basename( str_replace( $local_destination, '', $destination ) );
551
- if ( '.' == $destination_name ) {
552
- $destination_name = '';
553
- }
554
-
555
- $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' );
556
-
557
- /**
558
- * Filters the installation response after the installation has finished.
559
- *
560
- * @since 2.8.0
561
- *
562
- * @param bool $response Installation response.
563
- * @param array $hook_extra Extra arguments passed to hooked filters.
564
- * @param array $result Installation result data.
565
- */
566
- $res = apply_filters( 'upgrader_post_install', true, $args['hook_extra'], $this->result );
567
-
568
- if ( is_wp_error( $res ) ) {
569
- $this->result = $res;
570
- return $res;
571
- }
572
-
573
- //Bombard the calling function will all the info which we've just used.
574
- return $this->result;
575
- }
576
- }
1
+ <?php
2
+
3
+ namespace CFF\Helpers;
4
+
5
+ use WP_Error;
6
+ use WP_Upgrader;
7
+ use WP_Filesystem_Base;
8
+
9
+ /** \WP_Upgrader class */
10
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
11
+
12
+ /** \Plugin_Upgrader class */
13
+ require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
14
+
15
+ /**
16
+ * In WP 5.3 a PHP 5.6 splat operator (...$args) was added to \WP_Upgrader_Skin::feedback().
17
+ * We need to remove all calls to *Skin::feedback() method, as we can't override it in own Skins
18
+ * without breaking support for PHP 5.3-5.5.
19
+ *
20
+ * @internal Please do not use this class outside of core WPForms development. May be removed at any time.
21
+ *
22
+ * @since 1.5.6.1
23
+ */
24
+ class PluginSilentUpgrader extends \Plugin_Upgrader {
25
+
26
+ /**
27
+ * Run an upgrade/installation.
28
+ *
29
+ * Attempts to download the package (if it is not a local file), unpack it, and
30
+ * install it in the destination folder.
31
+ *
32
+ * @since 1.5.6.1
33
+ *
34
+ * @param array $options {
35
+ * Array or string of arguments for upgrading/installing a package.
36
+ *
37
+ * @type string $package The full path or URI of the package to install.
38
+ * Default empty.
39
+ * @type string $destination The full path to the destination folder.
40
+ * Default empty.
41
+ * @type bool $clear_destination Whether to delete any files already in the
42
+ * destination folder. Default false.
43
+ * @type bool $clear_working Whether to delete the files form the working
44
+ * directory after copying to the destination.
45
+ * Default false.
46
+ * @type bool $abort_if_destination_exists Whether to abort the installation if the destination
47
+ * folder already exists. When true, `$clear_destination`
48
+ * should be false. Default true.
49
+ * @type bool $is_multi Whether this run is one of multiple upgrade/installation
50
+ * actions being performed in bulk. When true, the skin
51
+ * WP_Upgrader::header() and WP_Upgrader::footer()
52
+ * aren't called. Default false.
53
+ * @type array $hook_extra Extra arguments to pass to the filter hooks called by
54
+ * WP_Upgrader::run().
55
+ * }
56
+ * @return array|false|WP_error The result from self::install_package() on success, otherwise a WP_Error,
57
+ * or false if unable to connect to the filesystem.
58
+ */
59
+ public function run( $options ) {
60
+
61
+ $defaults = array(
62
+ 'package' => '', // Please always pass this.
63
+ 'destination' => '', // And this
64
+ 'clear_destination' => false,
65
+ 'abort_if_destination_exists' => true, // Abort if the Destination directory exists, Pass clear_destination as false please
66
+ 'clear_working' => true,
67
+ 'is_multi' => false,
68
+ 'hook_extra' => array(), // Pass any extra $hook_extra args here, this will be passed to any hooked filters.
69
+ );
70
+
71
+ $options = wp_parse_args( $options, $defaults );
72
+
73
+ /**
74
+ * Filters the package options before running an update.
75
+ *
76
+ * See also {@see 'upgrader_process_complete'}.
77
+ *
78
+ * @since 4.3.0
79
+ *
80
+ * @param array $options {
81
+ * Options used by the upgrader.
82
+ *
83
+ * @type string $package Package for update.
84
+ * @type string $destination Update location.
85
+ * @type bool $clear_destination Clear the destination resource.
86
+ * @type bool $clear_working Clear the working resource.
87
+ * @type bool $abort_if_destination_exists Abort if the Destination directory exists.
88
+ * @type bool $is_multi Whether the upgrader is running multiple times.
89
+ * @type array $hook_extra {
90
+ * Extra hook arguments.
91
+ *
92
+ * @type string $action Type of action. Default 'update'.
93
+ * @type string $type Type of update process. Accepts 'plugin', 'theme', or 'core'.
94
+ * @type bool $bulk Whether the update process is a bulk update. Default true.
95
+ * @type string $plugin Path to the plugin file relative to the plugins directory.
96
+ * @type string $theme The stylesheet or template name of the theme.
97
+ * @type string $language_update_type The language pack update type. Accepts 'plugin', 'theme',
98
+ * or 'core'.
99
+ * @type object $language_update The language pack update offer.
100
+ * }
101
+ * }
102
+ */
103
+ $options = apply_filters( 'upgrader_package_options', $options );
104
+
105
+ if ( ! $options['is_multi'] ) { // call $this->header separately if running multiple times
106
+ $this->skin->header();
107
+ }
108
+
109
+ // Connect to the Filesystem first.
110
+ $res = $this->fs_connect( array( WP_CONTENT_DIR, $options['destination'] ) );
111
+ // Mainly for non-connected filesystem.
112
+ if ( ! $res ) {
113
+ if ( ! $options['is_multi'] ) {
114
+ $this->skin->footer();
115
+ }
116
+ return false;
117
+ }
118
+
119
+ $this->skin->before();
120
+
121
+ if ( is_wp_error( $res ) ) {
122
+ $this->skin->error( $res );
123
+ $this->skin->after();
124
+ if ( ! $options['is_multi'] ) {
125
+ $this->skin->footer();
126
+ }
127
+ return $res;
128
+ }
129
+
130
+ /*
131
+ * Download the package (Note, This just returns the filename
132
+ * of the file if the package is a local file)
133
+ */
134
+ $download = $this->download_package( $options['package'], true );
135
+
136
+ // Allow for signature soft-fail.
137
+ // WARNING: This may be removed in the future.
138
+ if ( is_wp_error( $download ) && $download->get_error_data( 'softfail-filename' ) ) {
139
+
140
+ // Don't output the 'no signature could be found' failure message for now.
141
+ if ( 'signature_verification_no_signature' != $download->get_error_code() || WP_DEBUG ) {
142
+ // Outout the failure error as a normal feedback, and not as an error:
143
+ //$this->skin->feedback( $download->get_error_message() );
144
+
145
+ // Report this failure back to WordPress.org for debugging purposes.
146
+ wp_version_check(
147
+ array(
148
+ 'signature_failure_code' => $download->get_error_code(),
149
+ 'signature_failure_data' => $download->get_error_data(),
150
+ )
151
+ );
152
+ }
153
+
154
+ // Pretend this error didn't happen.
155
+ $download = $download->get_error_data( 'softfail-filename' );
156
+ }
157
+
158
+ if ( is_wp_error( $download ) ) {
159
+ $this->skin->error( $download );
160
+ $this->skin->after();
161
+ if ( ! $options['is_multi'] ) {
162
+ $this->skin->footer();
163
+ }
164
+ return $download;
165
+ }
166
+
167
+ $delete_package = ( $download != $options['package'] ); // Do not delete a "local" file
168
+
169
+ // Unzips the file into a temporary directory.
170
+ $working_dir = $this->unpack_package( $download, $delete_package );
171
+ if ( is_wp_error( $working_dir ) ) {
172
+ $this->skin->error( $working_dir );
173
+ $this->skin->after();
174
+ if ( ! $options['is_multi'] ) {
175
+ $this->skin->footer();
176
+ }
177
+ return $working_dir;
178
+ }
179
+
180
+ // With the given options, this installs it to the destination directory.
181
+ $result = $this->install_package(
182
+ array(
183
+ 'source' => $working_dir,
184
+ 'destination' => $options['destination'],
185
+ 'clear_destination' => $options['clear_destination'],
186
+ 'abort_if_destination_exists' => $options['abort_if_destination_exists'],
187
+ 'clear_working' => $options['clear_working'],
188
+ 'hook_extra' => $options['hook_extra'],
189
+ )
190
+ );
191
+
192
+ $this->skin->set_result( $result );
193
+ if ( is_wp_error( $result ) ) {
194
+ $this->skin->error( $result );
195
+ //$this->skin->feedback( 'process_failed' );
196
+ } else {
197
+ // Installation succeeded.
198
+ //$this->skin->feedback( 'process_success' );
199
+ }
200
+
201
+ $this->skin->after();
202
+
203
+ if ( ! $options['is_multi'] ) {
204
+
205
+ /**
206
+ * Fires when the upgrader process is complete.
207
+ *
208
+ * See also {@see 'upgrader_package_options'}.
209
+ *
210
+ * @since 3.6.0
211
+ * @since 3.7.0 Added to WP_Upgrader::run().
212
+ * @since 4.6.0 `$translations` was added as a possible argument to `$hook_extra`.
213
+ *
214
+ * @param WP_Upgrader $this WP_Upgrader instance. In other contexts, $this, might be a
215
+ * Theme_Upgrader, Plugin_Upgrader, Core_Upgrade, or Language_Pack_Upgrader instance.
216
+ * @param array $hook_extra {
217
+ * Array of bulk item update data.
218
+ *
219
+ * @type string $action Type of action. Default 'update'.
220
+ * @type string $type Type of update process. Accepts 'plugin', 'theme', 'translation', or 'core'.
221
+ * @type bool $bulk Whether the update process is a bulk update. Default true.
222
+ * @type array $plugins Array of the basename paths of the plugins' main files.
223
+ * @type array $themes The theme slugs.
224
+ * @type array $translations {
225
+ * Array of translations update data.
226
+ *
227
+ * @type string $language The locale the translation is for.
228
+ * @type string $type Type of translation. Accepts 'plugin', 'theme', or 'core'.
229
+ * @type string $slug Text domain the translation is for. The slug of a theme/plugin or
230
+ * 'default' for core translations.
231
+ * @type string $version The version of a theme, plugin, or core.
232
+ * }
233
+ * }
234
+ */
235
+ do_action( 'upgrader_process_complete', $this, $options['hook_extra'] );
236
+
237
+ $this->skin->footer();
238
+ }
239
+
240
+ return $result;
241
+ }
242
+
243
+ /**
244
+ * Toggle maintenance mode for the site.
245
+ *
246
+ * Create/delete the maintenance file to enable/disable maintenance mode.
247
+ *
248
+ * @since 2.8.0
249
+ *
250
+ * @global WP_Filesystem_Base $wp_filesystem Subclass
251
+ *
252
+ * @param bool $enable True to enable maintenance mode, false to disable.
253
+ */
254
+ public function maintenance_mode( $enable = false ) {
255
+ global $wp_filesystem;
256
+ $file = $wp_filesystem->abspath() . '.maintenance';
257
+ if ( $enable ) {
258
+ //$this->skin->feedback( 'maintenance_start' );
259
+ // Create maintenance file to signal that we are upgrading
260
+ $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
261
+ $wp_filesystem->delete( $file );
262
+ $wp_filesystem->put_contents( $file, $maintenance_string, FS_CHMOD_FILE );
263
+ } elseif ( ! $enable && $wp_filesystem->exists( $file ) ) {
264
+ //$this->skin->feedback( 'maintenance_end' );
265
+ $wp_filesystem->delete( $file );
266
+ }
267
+ }
268
+
269
+ /**
270
+ * Download a package.
271
+ *
272
+ * @since 2.8.0
273
+ *
274
+ * @param string $package The URI of the package. If this is the full path to an
275
+ * existing local file, it will be returned untouched.
276
+ * @param bool $check_signatures Whether to validate file signatures. Default false.
277
+ * @return string|WP_Error The full path to the downloaded package file, or a WP_Error object.
278
+ */
279
+ public function download_package( $package, $check_signatures = false ) {
280
+
281
+ /**
282
+ * Filters whether to return the package.
283
+ *
284
+ * @since 3.7.0
285
+ *
286
+ * @param bool $reply Whether to bail without returning the package.
287
+ * Default false.
288
+ * @param string $package The package file name.
289
+ * @param WP_Upgrader $this The WP_Upgrader instance.
290
+ */
291
+ $reply = apply_filters( 'upgrader_pre_download', false, $package, $this );
292
+ if ( false !== $reply ) {
293
+ return $reply;
294
+ }
295
+
296
+ if ( ! preg_match( '!^(http|https|ftp)://!i', $package ) && file_exists( $package ) ) { //Local file or remote?
297
+ return $package; //must be a local file..
298
+ }
299
+
300
+ if ( empty( $package ) ) {
301
+ return new WP_Error( 'no_package', $this->strings['no_package'] );
302
+ }
303
+
304
+ //$this->skin->feedback( 'downloading_package', $package );
305
+
306
+ $download_file = download_url( $package, 300, $check_signatures );
307
+
308
+ if ( is_wp_error( $download_file ) && ! $download_file->get_error_data( 'softfail-filename' ) ) {
309
+ return new WP_Error( 'download_failed', $this->strings['download_failed'], $download_file->get_error_message() );
310
+ }
311
+
312
+ return $download_file;
313
+ }
314
+
315
+ /**
316
+ * Unpack a compressed package file.
317
+ *
318
+ * @since 2.8.0
319
+ *
320
+ * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
321
+ *
322
+ * @param string $package Full path to the package file.
323
+ * @param bool $delete_package Optional. Whether to delete the package file after attempting
324
+ * to unpack it. Default true.
325
+ * @return string|WP_Error The path to the unpacked contents, or a WP_Error on failure.
326
+ */
327
+ public function unpack_package( $package, $delete_package = true ) {
328
+ global $wp_filesystem;
329
+
330
+ //$this->skin->feedback( 'unpack_package' );
331
+
332
+ $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
333
+
334
+ //Clean up contents of upgrade directory beforehand.
335
+ $upgrade_files = $wp_filesystem->dirlist( $upgrade_folder );
336
+ if ( ! empty( $upgrade_files ) ) {
337
+ foreach ( $upgrade_files as $file ) {
338
+ $wp_filesystem->delete( $upgrade_folder . $file['name'], true );
339
+ }
340
+ }
341
+
342
+ // We need a working directory - Strip off any .tmp or .zip suffixes
343
+ $working_dir = $upgrade_folder . basename( basename( $package, '.tmp' ), '.zip' );
344
+
345
+ // Clean up working directory
346
+ if ( $wp_filesystem->is_dir( $working_dir ) ) {
347
+ $wp_filesystem->delete( $working_dir, true );
348
+ }
349
+
350
+ // Unzip package to working directory
351
+ $result = unzip_file( $package, $working_dir );
352
+
353
+ // Once extracted, delete the package if required.
354
+ if ( $delete_package ) {
355
+ unlink( $package );
356
+ }
357
+
358
+ if ( is_wp_error( $result ) ) {
359
+ $wp_filesystem->delete( $working_dir, true );
360
+ if ( 'incompatible_archive' == $result->get_error_code() ) {
361
+ return new WP_Error( 'incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data() );
362
+ }
363
+ return $result;
364
+ }
365
+
366
+ return $working_dir;
367
+ }
368
+
369
+ /**
370
+ * Install a package.
371
+ *
372
+ * Copies the contents of a package form a source directory, and installs them in
373
+ * a destination directory. Optionally removes the source. It can also optionally
374
+ * clear out the destination folder if it already exists.
375
+ *
376
+ * @since 2.8.0
377
+ *
378
+ * @global WP_Filesystem_Base $wp_filesystem WordPress filesystem subclass.
379
+ * @global array $wp_theme_directories
380
+ *
381
+ * @param array|string $args {
382
+ * Optional. Array or string of arguments for installing a package. Default empty array.
383
+ *
384
+ * @type string $source Required path to the package source. Default empty.
385
+ * @type string $destination Required path to a folder to install the package in.
386
+ * Default empty.
387
+ * @type bool $clear_destination Whether to delete any files already in the destination
388
+ * folder. Default false.
389
+ * @type bool $clear_working Whether to delete the files form the working directory
390
+ * after copying to the destination. Default false.
391
+ * @type bool $abort_if_destination_exists Whether to abort the installation if
392
+ * the destination folder already exists. Default true.
393
+ * @type array $hook_extra Extra arguments to pass to the filter hooks called by
394
+ * WP_Upgrader::install_package(). Default empty array.
395
+ * }
396
+ *
397
+ * @return array|WP_Error The result (also stored in `WP_Upgrader::$result`), or a WP_Error on failure.
398
+ */
399
+ public function install_package( $args = array() ) {
400
+ global $wp_filesystem, $wp_theme_directories;
401
+
402
+ $defaults = array(
403
+ 'source' => '', // Please always pass this
404
+ 'destination' => '', // and this
405
+ 'clear_destination' => false,
406
+ 'clear_working' => false,
407
+ 'abort_if_destination_exists' => true,
408
+ 'hook_extra' => array(),
409
+ );
410
+
411
+ $args = wp_parse_args( $args, $defaults );
412
+
413
+ // These were previously extract()'d.
414
+ $source = $args['source'];
415
+ $destination = $args['destination'];
416
+ $clear_destination = $args['clear_destination'];
417
+
418
+ set_time_limit( 300 );
419
+
420
+ if ( empty( $source ) || empty( $destination ) ) {
421
+ return new WP_Error( 'bad_request', $this->strings['bad_request'] );
422
+ }
423
+ //$this->skin->feedback( 'installing_package' );
424
+
425
+ /**
426
+ * Filters the install response before the installation has started.
427
+ *
428
+ * Returning a truthy value, or one that could be evaluated as a WP_Error
429
+ * will effectively short-circuit the installation, returning that value
430
+ * instead.
431
+ *
432
+ * @since 2.8.0
433
+ *
434
+ * @param bool|WP_Error $response Response.
435
+ * @param array $hook_extra Extra arguments passed to hooked filters.
436
+ */
437
+ $res = apply_filters( 'upgrader_pre_install', true, $args['hook_extra'] );
438
+
439
+ if ( is_wp_error( $res ) ) {
440
+ return $res;
441
+ }
442
+
443
+ //Retain the Original source and destinations
444
+ $remote_source = $args['source'];
445
+ $local_destination = $destination;
446
+
447
+ $source_files = array_keys( $wp_filesystem->dirlist( $remote_source ) );
448
+ $remote_destination = $wp_filesystem->find_folder( $local_destination );
449
+
450
+ //Locate which directory to copy to the new folder, This is based on the actual folder holding the files.
451
+ if ( 1 == count( $source_files ) && $wp_filesystem->is_dir( trailingslashit( $args['source'] ) . $source_files[0] . '/' ) ) { //Only one folder? Then we want its contents.
452
+ $source = trailingslashit( $args['source'] ) . trailingslashit( $source_files[0] );
453
+ } elseif ( count( $source_files ) == 0 ) {
454
+ return new WP_Error( 'incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files'] ); // There are no files?
455
+ } else { // It's only a single file, the upgrader will use the folder name of this file as the destination folder. Folder name is based on zip filename.
456
+ $source = trailingslashit( $args['source'] );
457
+ }
458
+
459
+ /**
460
+ * Filters the source file location for the upgrade package.
461
+ *
462
+ * @since 2.8.0
463
+ * @since 4.4.0 The $hook_extra parameter became available.
464
+ *
465
+ * @param string $source File source location.
466
+ * @param string $remote_source Remote file source location.
467
+ * @param WP_Upgrader $this WP_Upgrader instance.
468
+ * @param array $hook_extra Extra arguments passed to hooked filters.
469
+ */
470
+ $source = apply_filters( 'upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra'] );
471
+
472
+ if ( is_wp_error( $source ) ) {
473
+ return $source;
474
+ }
475
+
476
+ // Has the source location changed? If so, we need a new source_files list.
477
+ if ( $source !== $remote_source ) {
478
+ $source_files = array_keys( $wp_filesystem->dirlist( $source ) );
479
+ }
480
+
481
+ /*
482
+ * Protection against deleting files in any important base directories.
483
+ * Theme_Upgrader & Plugin_Upgrader also trigger this, as they pass the
484
+ * destination directory (WP_PLUGIN_DIR / wp-content/themes) intending
485
+ * to copy the directory into the directory, whilst they pass the source
486
+ * as the actual files to copy.
487
+ */
488
+ $protected_directories = array( ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes' );
489
+
490
+ if ( is_array( $wp_theme_directories ) ) {
491
+ $protected_directories = array_merge( $protected_directories, $wp_theme_directories );
492
+ }
493
+
494
+ if ( in_array( $destination, $protected_directories ) ) {
495
+ $remote_destination = trailingslashit( $remote_destination ) . trailingslashit( basename( $source ) );
496
+ $destination = trailingslashit( $destination ) . trailingslashit( basename( $source ) );
497
+ }
498
+
499
+ if ( $clear_destination ) {
500
+ // We're going to clear the destination if there's something there.
501
+ //$this->skin->feedback( 'remove_old' );
502
+
503
+ $removed = $this->clear_destination( $remote_destination );
504
+
505
+ /**
506
+ * Filters whether the upgrader cleared the destination.
507
+ *
508
+ * @since 2.8.0
509
+ *
510
+ * @param mixed $removed Whether the destination was cleared. true on success, WP_Error on failure
511
+ * @param string $local_destination The local package destination.
512
+ * @param string $remote_destination The remote package destination.
513
+ * @param array $hook_extra Extra arguments passed to hooked filters.
514
+ */
515
+ $removed = apply_filters( 'upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra'] );
516
+
517
+ if ( is_wp_error( $removed ) ) {
518
+ return $removed;
519
+ }
520
+ } elseif ( $args['abort_if_destination_exists'] && $wp_filesystem->exists( $remote_destination ) ) {
521
+ //If we're not clearing the destination folder and something exists there already, Bail.
522
+ //But first check to see if there are actually any files in the folder.
523
+ $_files = $wp_filesystem->dirlist( $remote_destination );
524
+ if ( ! empty( $_files ) ) {
525
+ $wp_filesystem->delete( $remote_source, true ); //Clear out the source files.
526
+ return new WP_Error( 'folder_exists', $this->strings['folder_exists'], $remote_destination );
527
+ }
528
+ }
529
+
530
+ //Create destination if needed
531
+ if ( ! $wp_filesystem->exists( $remote_destination ) ) {
532
+ if ( ! $wp_filesystem->mkdir( $remote_destination, FS_CHMOD_DIR ) ) {
533
+ return new WP_Error( 'mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination );
534
+ }
535
+ }
536
+ // Copy new version of item into place.
537
+ $result = copy_dir( $source, $remote_destination );
538
+ if ( is_wp_error( $result ) ) {
539
+ if ( $args['clear_working'] ) {
540
+ $wp_filesystem->delete( $remote_source, true );
541
+ }
542
+ return $result;
543
+ }
544
+
545
+ //Clear the Working folder?
546
+ if ( $args['clear_working'] ) {
547
+ $wp_filesystem->delete( $remote_source, true );
548
+ }
549
+
550
+ $destination_name = basename( str_replace( $local_destination, '', $destination ) );
551
+ if ( '.' == $destination_name ) {
552
+ $destination_name = '';
553
+ }
554
+
555
+ $this->result = compact( 'source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination' );
556
+
557
+ /**
558
+ * Filters the installation response after the installation has finished.
559
+ *
560
+ * @since 2.8.0
561
+ *
562
+ * @param bool $response Installation response.
563
+ * @param array $hook_extra Extra arguments passed to hooked filters.
564
+ * @param array $result Installation result data.
565
+ */
566
+ $res = apply_filters( 'upgrader_post_install', true, $args['hook_extra'], $this->result );
567
+
568
+ if ( is_wp_error( $res ) ) {
569
+ $this->result = $res;
570
+ return $res;
571
+ }
572
+
573
+ //Bombard the calling function will all the info which we've just used.
574
+ return $this->result;
575
+ }
576
+ }
admin/PluginSilentUpgraderSkin.php CHANGED
@@ -1,57 +1,57 @@
1
- <?php
2
-
3
- namespace CFF\Helpers;
4
-
5
- /** \WP_Upgrader_Skin class */
6
- require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
7
-
8
- /**
9
- * Class PluginSilentUpgraderSkin.
10
- *
11
- * @internal Please do not use this class outside of core WPForms development. May be removed at any time.
12
- *
13
- * @since 1.5.6.1
14
- */
15
- class PluginSilentUpgraderSkin extends \WP_Upgrader_Skin {
16
-
17
- /**
18
- * Empty out the header of its HTML content and only check to see if it has
19
- * been performed or not.
20
- *
21
- * @since 1.5.6.1
22
- */
23
- public function header() {
24
- }
25
-
26
- /**
27
- * Empty out the footer of its HTML contents.
28
- *
29
- * @since 1.5.6.1
30
- */
31
- public function footer() {
32
- }
33
-
34
- /**
35
- * Instead of outputting HTML for errors, just return them.
36
- * Ajax request will just ignore it.
37
- *
38
- * @since 1.5.6.1
39
- *
40
- * @param array $errors Array of errors with the install process.
41
- *
42
- * @return array
43
- */
44
- public function error( $errors ) {
45
- return $errors;
46
- }
47
-
48
- /**
49
- * Empty out JavaScript output that calls function to decrement the update counts.
50
- *
51
- * @since 1.5.6.1
52
- *
53
- * @param string $type Type of update count to decrement.
54
- */
55
- public function decrement_update_count( $type ) {
56
- }
57
- }
1
+ <?php
2
+
3
+ namespace CFF\Helpers;
4
+
5
+ /** \WP_Upgrader_Skin class */
6
+ require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
7
+
8
+ /**
9
+ * Class PluginSilentUpgraderSkin.
10
+ *
11
+ * @internal Please do not use this class outside of core WPForms development. May be removed at any time.
12
+ *
13
+ * @since 1.5.6.1
14
+ */
15
+ class PluginSilentUpgraderSkin extends \WP_Upgrader_Skin {
16
+
17
+ /**
18
+ * Empty out the header of its HTML content and only check to see if it has
19
+ * been performed or not.
20
+ *
21
+ * @since 1.5.6.1
22
+ */
23
+ public function header() {
24
+ }
25
+
26
+ /**
27
+ * Empty out the footer of its HTML contents.
28
+ *
29
+ * @since 1.5.6.1
30
+ */
31
+ public function footer() {
32
+ }
33
+
34
+ /**
35
+ * Instead of outputting HTML for errors, just return them.
36
+ * Ajax request will just ignore it.
37
+ *
38
+ * @since 1.5.6.1
39
+ *
40
+ * @param array $errors Array of errors with the install process.
41
+ *
42
+ * @return array
43
+ */
44
+ public function error( $errors ) {
45
+ return $errors;
46
+ }
47
+
48
+ /**
49
+ * Empty out JavaScript output that calls function to decrement the update counts.
50
+ *
51
+ * @since 1.5.6.1
52
+ *
53
+ * @param string $type Type of update count to decrement.
54
+ */
55
+ public function decrement_update_count( $type ) {
56
+ }
57
+ }
admin/addon-functions.php CHANGED
@@ -1,175 +1,176 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
-
4
- /**
5
- * Deactivate addon.
6
- *
7
- * @since 1.0.0
8
- */
9
- function cff_deactivate_addon() {
10
-
11
- // Run a security check.
12
- check_ajax_referer( 'cff-admin', 'nonce' );
13
-
14
- // Check for permissions.
15
- if ( ! current_user_can( 'manage_instagram_feed_options' ) ) {
16
- wp_send_json_error();
17
- }
18
-
19
- $type = 'addon';
20
- if ( ! empty( $_POST['type'] ) ) {
21
- $type = sanitize_key( $_POST['type'] );
22
- }
23
-
24
- if ( isset( $_POST['plugin'] ) ) {
25
- deactivate_plugins( $_POST['plugin'] );
26
-
27
- if ( 'plugin' === $type ) {
28
- wp_send_json_success( esc_html__( 'Plugin deactivated.', 'custom-facebook-feed' ) );
29
- } else {
30
- wp_send_json_success( esc_html__( 'Addon deactivated.', 'custom-facebook-feed' ) );
31
- }
32
- }
33
-
34
- wp_send_json_error( esc_html__( 'Could not deactivate the addon. Please deactivate from the Plugins page.', 'custom-facebook-feed' ) );
35
- }
36
- add_action( 'wp_ajax_cff_deactivate_addon', 'cff_deactivate_addon' );
37
-
38
- /**
39
- * Activate addon.
40
- *
41
- * @since 1.0.0
42
- */
43
- function cff_activate_addon() {
44
-
45
- // Run a security check.
46
- check_ajax_referer( 'cff-admin', 'nonce' );
47
-
48
- // Check for permissions.
49
- if ( ! current_user_can( 'manage_options' ) ) {
50
- wp_send_json_error();
51
- }
52
-
53
- if ( isset( $_POST['plugin'] ) ) {
54
-
55
- $type = 'addon';
56
- if ( ! empty( $_POST['type'] ) ) {
57
- $type = sanitize_key( $_POST['type'] );
58
- }
59
-
60
- $activate = activate_plugins( $_POST['plugin'] );
61
-
62
- if ( ! is_wp_error( $activate ) ) {
63
- if ( 'plugin' === $type ) {
64
- wp_send_json_success( esc_html__( 'Plugin activated.', 'custom-facebook-feed' ) );
65
- } else {
66
- wp_send_json_success( esc_html__( 'Addon activated.', 'custom-facebook-feed' ) );
67
- }
68
- }
69
- }
70
-
71
- wp_send_json_error( esc_html__( 'Could not activate addon. Please activate from the Plugins page.', 'custom-facebook-feed' ) );
72
- }
73
- add_action( 'wp_ajax_cff_activate_addon', 'cff_activate_addon' );
74
-
75
- /**
76
- * Install addon.
77
- *
78
- * @since 1.0.0
79
- */
80
- function cff_install_addon() {
81
-
82
- // Run a security check.
83
- check_ajax_referer( 'cff-admin', 'nonce' );
84
-
85
- // Check for permissions.
86
- if ( ! current_user_can( 'manage_options' ) ) {
87
- wp_send_json_error();
88
- }
89
-
90
- $error = esc_html__( 'Could not install addon. Please download from smashballoon.com and install manually.', 'custom-facebook-feed' );
91
-
92
- if ( empty( $_POST['plugin'] ) ) {
93
- wp_send_json_error( $error );
94
- }
95
-
96
- // Set the current screen to avoid undefined notices.
97
- set_current_screen( 'cff-about' );
98
-
99
- // Prepare variables.
100
- $url = esc_url_raw(
101
- add_query_arg(
102
- array(
103
- 'page' => 'cff-about',
104
- ),
105
- admin_url( 'admin.php' )
106
- )
107
- );
108
-
109
- $creds = request_filesystem_credentials( $url, '', false, false, null );
110
-
111
- // Check for file system permissions.
112
- if ( false === $creds ) {
113
- wp_send_json_error( $error );
114
- }
115
-
116
- if ( ! WP_Filesystem( $creds ) ) {
117
- wp_send_json_error( $error );
118
- }
119
-
120
- /*
121
- * We do not need any extra credentials if we have gotten this far, so let's install the plugin.
122
- */
123
-
124
- require_once CFF_PLUGIN_DIR . 'admin/class-install-skin.php';
125
-
126
- // Do not allow WordPress to search/download translations, as this will break JS output.
127
- remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
128
-
129
- // Create the plugin upgrader with our custom skin.
130
- $installer = new CFF\Helpers\PluginSilentUpgrader( new CFF_Install_Skin() );
131
-
132
- // Error check.
133
- if ( ! method_exists( $installer, 'install' ) || empty( $_POST['plugin'] ) ) {
134
- wp_send_json_error( $error );
135
- }
136
-
137
- $installer->install( $_POST['plugin'] ); // phpcs:ignore
138
-
139
- // Flush the cache and return the newly installed plugin basename.
140
- wp_cache_flush();
141
-
142
- $plugin_basename = $installer->plugin_info();
143
-
144
- if ( $plugin_basename ) {
145
-
146
- $type = 'addon';
147
- if ( ! empty( $_POST['type'] ) ) {
148
- $type = sanitize_key( $_POST['type'] );
149
- }
150
-
151
- // Activate the plugin silently.
152
- $activated = activate_plugin( $plugin_basename );
153
-
154
- if ( ! is_wp_error( $activated ) ) {
155
- wp_send_json_success(
156
- array(
157
- 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed & activated.', 'custom-facebook-feed' ) : esc_html__( 'Addon installed & activated.', 'custom-facebook-feed' ),
158
- 'is_activated' => true,
159
- 'basename' => $plugin_basename,
160
- )
161
- );
162
- } else {
163
- wp_send_json_success(
164
- array(
165
- 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed.', 'custom-facebook-feed' ) : esc_html__( 'Addon installed.', 'custom-facebook-feed' ),
166
- 'is_activated' => false,
167
- 'basename' => $plugin_basename,
168
- )
169
- );
170
- }
171
- }
172
-
173
- wp_send_json_error( $error );
174
- }
175
add_action( 'wp_ajax_cff_install_addon', 'cff_install_addon' );
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
+
4
+ /**
5
+ * Deactivate addon.
6
+ *
7
+ * @since 1.0.0
8
+ */
9
+ function cff_deactivate_addon() {
10
+
11
+ // Run a security check.
12
+ check_ajax_referer( 'cff-admin', 'nonce' );
13
+ $cap = current_user_can( 'manage_custom_facebook_feed_options' ) ? 'manage_custom_facebook_feed_options' : 'manage_options';
14
+ $cap = apply_filters( 'cff_settings_pages_capability', $cap );
15
+ // Check for permissions.
16
+ if ( ! current_user_can( $cap ) ) {
17
+ wp_send_json_error();
18
+ }
19
+
20
+ $type = 'addon';
21
+ if ( ! empty( $_POST['type'] ) ) {
22
+ $type = sanitize_key( $_POST['type'] );
23
+ }
24
+
25
+ if ( isset( $_POST['plugin'] ) ) {
26
+ deactivate_plugins( $_POST['plugin'] );
27
+
28
+ if ( 'plugin' === $type ) {
29
+ wp_send_json_success( esc_html__( 'Plugin deactivated.', 'custom-facebook-feed' ) );
30
+ } else {
31
+ wp_send_json_success( esc_html__( 'Addon deactivated.', 'custom-facebook-feed' ) );
32
+ }
33
+ }
34
+
35
+ wp_send_json_error( esc_html__( 'Could not deactivate the addon. Please deactivate from the Plugins page.', 'custom-facebook-feed' ) );
36
+ }
37
+ add_action( 'wp_ajax_cff_deactivate_addon', 'cff_deactivate_addon' );
38
+
39
+ /**
40
+ * Activate addon.
41
+ *
42
+ * @since 1.0.0
43
+ */
44
+ function cff_activate_addon() {
45
+
46
+ // Run a security check.
47
+ check_ajax_referer( 'cff-admin', 'nonce' );
48
+
49
+ // Check for permissions.
50
+ if ( ! current_user_can( 'manage_options' ) ) {
51
+ wp_send_json_error();
52
+ }
53
+
54
+ if ( isset( $_POST['plugin'] ) ) {
55
+
56
+ $type = 'addon';
57
+ if ( ! empty( $_POST['type'] ) ) {
58
+ $type = sanitize_key( $_POST['type'] );
59
+ }
60
+
61
+ $activate = activate_plugins( $_POST['plugin'] );
62
+
63
+ if ( ! is_wp_error( $activate ) ) {
64
+ if ( 'plugin' === $type ) {
65
+ wp_send_json_success( esc_html__( 'Plugin activated.', 'custom-facebook-feed' ) );
66
+ } else {
67
+ wp_send_json_success( esc_html__( 'Addon activated.', 'custom-facebook-feed' ) );
68
+ }
69
+ }
70
+ }
71
+
72
+ wp_send_json_error( esc_html__( 'Could not activate addon. Please activate from the Plugins page.', 'custom-facebook-feed' ) );
73
+ }
74
+ add_action( 'wp_ajax_cff_activate_addon', 'cff_activate_addon' );
75
+
76
+ /**
77
+ * Install addon.
78
+ *
79
+ * @since 1.0.0
80
+ */
81
+ function cff_install_addon() {
82
+
83
+ // Run a security check.
84
+ check_ajax_referer( 'cff-admin', 'nonce' );
85
+
86
+ // Check for permissions.
87
+ if ( ! current_user_can( 'manage_options' ) ) {
88
+ wp_send_json_error();
89
+ }
90
+
91
+ $error = esc_html__( 'Could not install addon. Please download from smashballoon.com and install manually.', 'custom-facebook-feed' );
92
+
93
+ if ( empty( $_POST['plugin'] ) ) {
94
+ wp_send_json_error( $error );
95
+ }
96
+
97
+ // Set the current screen to avoid undefined notices.
98
+ set_current_screen( 'cff-about' );
99
+
100
+ // Prepare variables.
101
+ $url = esc_url_raw(
102
+ add_query_arg(
103
+ array(
104
+ 'page' => 'cff-about',
105
+ ),
106
+ admin_url( 'admin.php' )
107
+ )
108
+ );
109
+
110
+ $creds = request_filesystem_credentials( $url, '', false, false, null );
111
+
112
+ // Check for file system permissions.
113
+ if ( false === $creds ) {
114
+ wp_send_json_error( $error );
115
+ }
116
+
117
+ if ( ! WP_Filesystem( $creds ) ) {
118
+ wp_send_json_error( $error );
119
+ }
120
+
121
+ /*
122
+ * We do not need any extra credentials if we have gotten this far, so let's install the plugin.
123
+ */
124
+
125
+ require_once CFF_PLUGIN_DIR . 'admin/class-install-skin.php';
126
+
127
+ // Do not allow WordPress to search/download translations, as this will break JS output.
128
+ remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
129
+
130
+ // Create the plugin upgrader with our custom skin.
131
+ $installer = new CFF\Helpers\PluginSilentUpgrader( new CFF_Install_Skin() );
132
+
133
+ // Error check.
134
+ if ( ! method_exists( $installer, 'install' ) || empty( $_POST['plugin'] ) ) {
135
+ wp_send_json_error( $error );
136
+ }
137
+
138
+ $installer->install( $_POST['plugin'] ); // phpcs:ignore
139
+
140
+ // Flush the cache and return the newly installed plugin basename.
141
+ wp_cache_flush();
142
+
143
+ $plugin_basename = $installer->plugin_info();
144
+
145
+ if ( $plugin_basename ) {
146
+
147
+ $type = 'addon';
148
+ if ( ! empty( $_POST['type'] ) ) {
149
+ $type = sanitize_key( $_POST['type'] );
150
+ }
151
+
152
+ // Activate the plugin silently.
153
+ $activated = activate_plugin( $plugin_basename );
154
+
155
+ if ( ! is_wp_error( $activated ) ) {
156
+ wp_send_json_success(
157
+ array(
158
+ 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed & activated.', 'custom-facebook-feed' ) : esc_html__( 'Addon installed & activated.', 'custom-facebook-feed' ),
159
+ 'is_activated' => true,
160
+ 'basename' => $plugin_basename,
161
+ )
162
+ );
163
+ } else {
164
+ wp_send_json_success(
165
+ array(
166
+ 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed.', 'custom-facebook-feed' ) : esc_html__( 'Addon installed.', 'custom-facebook-feed' ),
167
+ 'is_activated' => false,
168
+ 'basename' => $plugin_basename,
169
+ )
170
+ );
171
+ }
172
+ }
173
+
174
+ wp_send_json_error( $error );
175
+ }
176
add_action( 'wp_ajax_cff_install_addon', 'cff_install_addon' );
admin/class-cff-about.php CHANGED
@@ -1,1351 +1,1351 @@
1
- <?php
2
-
3
- /**
4
- * About Sbi admin page class.
5
- *
6
- * @since 2.4/5.5
7
- */
8
- class CFF_About {
9
-
10
- /**
11
- * Admin menu page slug.
12
- *
13
- * @since 2.4/5.5
14
- *
15
- * @var string
16
- */
17
- const SLUG = 'cff-about';
18
-
19
- /**
20
- * Default view for a page.
21
- *
22
- * @since 2.4/5.5
23
- *
24
- * @var string
25
- */
26
- const DEFAULT_TAB = 'about';
27
-
28
- /**
29
- * Array of license types, that are considered being top level and has no features difference.
30
- *
31
- * @since 2.4/5.5
32
- *
33
- * @var array
34
- */
35
- public static $licenses_top = array( 'pro', 'agency', 'ultimate', 'elite' );
36
-
37
- /**
38
- * List of features that licenses are different with.
39
- *
40
- * @since 2.4/5.5
41
- *
42
- * @var array
43
- */
44
- public static $licenses_features = array();
45
-
46
- /**
47
- * The current active tab.
48
- *
49
- * @since 2.4/5.5
50
- *
51
- * @var string
52
- */
53
- public $view;
54
-
55
- /**
56
- * The core views.
57
- *
58
- * @since 2.4/5.5
59
- *
60
- * @var array
61
- */
62
- public $views = array();
63
-
64
- /**
65
- * Primary class constructor.
66
- *
67
- * @since 2.4/5.5
68
- */
69
- public function __construct() {
70
-
71
- // In old PHP we can't define this elsewhere.
72
- self::$licenses_features = array(
73
- 'entries' => esc_html__( 'Media Display', 'custom-facebook-feed' ),
74
- //'fields' => esc_html__( 'Layouts', 'custom-facebook-feed' ),
75
- // 'templates' => esc_html__( 'Post Display', 'custom-facebook-feed' ),
76
- //'conditionals' => esc_html__( 'Image and Video Display', 'custom-facebook-feed' ),
77
- 'addons' => esc_html__( 'Post Source', 'custom-facebook-feed' ),
78
- 'addons1' => esc_html__( 'Number of Posts', 'custom-facebook-feed' ),
79
- 'addons2' => esc_html__( 'Filtering', 'custom-facebook-feed' ),
80
-
81
- //'marketing' => esc_html__( 'Filtering', 'custom-facebook-feed' ),
82
- //'marketing' => esc_html__( 'Instagram Stories', 'custom-facebook-feed' ),
83
- 'payments' => esc_html__( 'Feed Layout', 'custom-facebook-feed' ),
84
- 'surveys' => esc_html__( 'Post Information', 'custom-facebook-feed' ),
85
- 'advanced' => esc_html__( 'Comments', 'custom-facebook-feed' ),
86
- 'extensions' => esc_html__( 'Extensions', 'custom-facebook-feed' ),
87
- 'support' => esc_html__( 'Customer Support', 'custom-facebook-feed' ),
88
- );
89
-
90
- // Maybe load tools page.
91
- add_action( 'admin_init', array( $this, 'init' ) );
92
- }
93
-
94
- /**
95
- * Determining if the user is viewing the our page, if so, party on.
96
- *
97
- * @since 2.4/5.5
98
- */
99
- public function init() {
100
-
101
- // Check what page we are on.
102
- $page = isset( $_GET['page'] ) ? $_GET['page'] : '';
103
-
104
- // Only load if we are actually on the settings page.
105
- if ( self::SLUG !== $page ) {
106
- return;
107
- }
108
-
109
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) );
110
-
111
- /*
112
- * Define the core views for the our tab.
113
- */
114
- $this->views = apply_filters(
115
- 'cff_admin_about_views',
116
- array(
117
- esc_html__( 'About Us', 'custom-facebook-feed' ) => array( 'about' ),
118
- esc_html__( 'Getting Started', 'custom-facebook-feed' ) => array( 'getting-started' ),
119
- )
120
- );
121
-
122
- $license = $this->get_license_type();
123
-
124
- if (
125
- (
126
- $license === 'pro' ||
127
- ! in_array( $license, self::$licenses_top, true )
128
- )
129
- //cff_debug()
130
- ) {
131
- $vs_tab_name = sprintf( /* translators: %1$s - current license type, %2$s - suggested license type. */
132
- esc_html__( '%1$s vs %2$s', 'custom-facebook-feed' ),
133
- ucfirst( $license ),
134
- $this->get_next_license( $license )
135
- );
136
-
137
- $this->views[ $vs_tab_name ] = array( 'versus' );
138
- }
139
-
140
- // Determine the current active settings tab.
141
- $this->view = ! empty( $_GET['view'] ) ? esc_html( $_GET['view'] ) : self::DEFAULT_TAB;
142
-
143
- // If the user tries to load an invalid view - fallback to About Us.
144
- if (
145
- ! in_array( $this->view, call_user_func_array( 'array_merge', $this->views ), true ) &&
146
- ! has_action( 'cff_admin_about_display_tab_' . sanitize_key( $this->view ) )
147
- ) {
148
- $this->view = self::DEFAULT_TAB;
149
- }
150
-
151
- add_action( 'cff_admin_page', array( $this, 'output' ) );
152
-
153
- // Hook for addons.
154
- do_action( 'cff_admin_about_init' );
155
- }
156
-
157
- /**
158
- * Enqueue assets for the the page.
159
- *
160
- * @since 2.4/5.5
161
- */
162
- public function enqueues() {
163
-
164
- wp_enqueue_script(
165
- 'jquery-matchheight',
166
- CFF_PLUGIN_URL . 'js/jquery.matchHeight-min.js',
167
- array( 'jquery' ),
168
- '0.7.0',
169
- false
170
- );
171
- }
172
-
173
- /**
174
- * Output the basic page structure.
175
- *
176
- * @since 2.4/5.5
177
- */
178
- public function output() {
179
-
180
- $show_nav = false;
181
- foreach ( $this->views as $view ) {
182
- if ( in_array( $this->view, (array) $view, true ) ) {
183
- $show_nav = true;
184
- break;
185
- }
186
- }
187
- ?>
188
-
189
- <div id="cff-admin-about" class="wrap cff-admin-wrap">
190
-
191
- <?php
192
- if ( $show_nav ) {
193
- $license = $this->get_license_type();
194
- $next_license = $this->get_next_license( $license );
195
- echo '<ul class="cff-admin-tabs">';
196
- foreach ( $this->views as $label => $view ) {
197
- $class = in_array( $this->view, $view, true ) ? 'active' : '';
198
- echo '<li>';
199
- printf(
200
- '<a href="%s" class="%s">%s</a>',
201
- esc_url( admin_url( 'admin.php?page=' . self::SLUG . '&view=' . sanitize_key( $view[0] ) ) ),
202
- esc_attr( $class ),
203
- esc_html( $label )
204
- );
205
- echo '</li>';
206
- }
207
- echo '</ul>';
208
- }
209
- ?>
210
-
211
- <h1 class="cff-h1-placeholder"></h1>
212
-
213
- <?php
214
- switch ( $this->view ) {
215
- case 'about':
216
- $this->output_about();
217
- break;
218
- case 'getting-started':
219
- $this->output_getting_started();
220
- break;
221
- case 'versus':
222
- $this->output_versus();
223
- break;
224
- default:
225
- do_action( 'cff_admin_about_display_tab_' . sanitize_key( $this->view ) );
226
- break;
227
- }
228
- ?>
229
-
230
- </div>
231
-
232
- <?php
233
- }
234
-
235
- /**
236
- * Display the About tab content.
237
- *
238
- * @since 2.4/5.5
239
- */
240
- protected function output_about() {
241
-
242
- $this->output_about_info();
243
- $this->output_about_addons();
244
- }
245
-
246
- /**
247
- * Display the General Info section of About tab.
248
- *
249
- * @since 1.5.8
250
- */
251
- protected function output_about_info() {
252
-
253
- ?>
254
-
255
- <div class="cff-admin-about-section cff-admin-columns">
256
-
257
- <div class="cff-admin-about-text" style="min-height: 340px;">
258
- <h3>
259
- <?php esc_html_e( 'Hello and welcome to the Custom Facebook Feed plugin, the most customizable, clean, and simple Facebook feed plugin in the world. At Smash Balloon, we build software that helps you create beautiful responsive social media feeds for your website in minutes.', 'custom-facebook-feed' ); ?>
260
- </h3>
261
-
262
- <p>
263
- <?php esc_html_e( 'Smash Balloon is a fun-loving WordPress plugin development company birthed into existence in early 2013. We specialize in creating plugins that are not only intuitive and simple to use, but also designed to integrate seamlessly into your website and allow you to display your social media content in powerful and unique ways. Over 1 million awesome people have decided to actively use our plugins, which is an incredible honor that we don’t take lightly. This compels us to try to provide the quickest and most effective customer support that we can, blowing users away with the best customer service they’ve ever experienced.', 'custom-facebook-feed' ); ?>
264
- </p>
265
- <p>
266
- <?php esc_html_e( 'We’re a small, but dedicated, team based in Minnesota in the USA.', 'custom-facebook-feed' ); ?>
267
- </p>
268
-
269
- </div>
270
-
271
- <div class="cff-admin-about-image cff-admin-column-last">
272
- <figure>
273
- <img src="<?php echo CFF_PLUGIN_URL; ?>img/about/team.jpg" alt="<?php esc_attr_e( 'The Sbi Team photo', 'custom-facebook-feed' ); ?>">
274
- <figcaption>
275
- <?php esc_html_e( 'The Smash Balloon Team', 'custom-facebook-feed' ); ?><br>
276
- </figcaption>
277
- </figure>
278
- </div>
279
-
280
- </div>
281
- <?php
282
- }
283
-
284
- /**
285
- * Display the Addons section of About tab.
286
- *
287
- * @since 1.5.8
288
- */
289
- protected function output_about_addons() {
290
-
291
- if ( ! current_user_can( 'manage_custom_facebook_feed_options' ) || version_compare( PHP_VERSION, '5.3.0' ) <= 0 ) {
292
- return;
293
- }
294
-
295
- $all_plugins = get_plugins();
296
- $am_plugins = $this->get_am_plugins();
297
-
298
- ?>
299
- <div id="cff-admin-addons">
300
- <div class="addons-container">
301
- <h3><?php echo __( 'Our Other Plugins', 'custom-facebook-feed' ); ?></h3>
302
- <?php
303
- foreach ( $am_plugins as $plugin => $details ) :
304
-
305
- $plugin_data = $this->get_plugin_data( $plugin, $details, $all_plugins );
306
-
307
- if ( $plugin === 'wpforms-lite/wpforms.php' ) {
308
- echo '<h3>' .__( 'Plugins We Recommend', 'custom-facebook-feed' ). '</h3>';
309
- }
310
-
311
- ?>
312
- <div class="addon-container">
313
- <div class="addon-item">
314
- <div class="details cff-clear">
315
- <img src="<?php echo esc_url( $plugin_data['details']['icon'] ); ?>">
316
- <h5 class="addon-name">
317
- <?php echo esc_html( $plugin_data['details']['name'] ); ?>
318
- </h5>
319
- <p class="addon-desc">
320
- <?php echo wp_kses_post( $plugin_data['details']['desc'] ); ?>
321
- </p>
322
- </div>
323
- <div class="actions cff-clear">
324
- <div class="status">
325
- <strong>
326
- <?php
327
- printf(
328
- /* translators: %s - addon status label. */
329
- esc_html__( 'Status: %s', 'custom-facebook-feed' ),
330
- '<span class="status-label ' . esc_attr( $plugin_data['status_class'] ) . '">' . wp_kses_post( $plugin_data['status_text'] ) . '</span>'
331
- );
332
- ?>
333
- </strong>
334
- </div>
335
- <div class="action-button">
336
- <button class="<?php echo esc_attr( $plugin_data['action_class'] ); ?>" data-plugin="<?php echo esc_attr( $plugin_data['plugin_src'] ); ?>" data-type="plugin">
337
- <?php echo wp_kses_post( $plugin_data['action_text'] ); ?>
338
- </button>
339
- </div>
340
- </div>
341
- </div>
342
- </div>
343
- <?php endforeach; ?>
344
- </div>
345
- </div>
346
- <?php
347
- }
348
-
349
- /**
350
- * Get AM plugin data to display in the Addons section of About tab.
351
- *
352
- * @since 1.5.8
353
- *
354
- * @param string $plugin Plugin slug.
355
- * @param array $details Plugin details.
356
- * @param array $all_plugins List of all plugins.
357
- *
358
- * @return array
359
- */
360
- protected function get_plugin_data( $plugin, $details, $all_plugins ) {
361
-
362
- $have_pro = ( ! empty( $details['pro'] ) && ! empty( $details['pro']['plug'] ) );
363
- $show_pro = false;
364
-
365
- $plugin_data = array();
366
-
367
- if ( $have_pro ) {
368
- if ( array_key_exists( $plugin, $all_plugins ) ) {
369
- if ( is_plugin_active( $plugin ) ) {
370
- $show_pro = true;
371
- }
372
- }
373
- if ( array_key_exists( $details['pro']['plug'], $all_plugins ) ) {
374
- $show_pro = true;
375
- }
376
- if ( $show_pro ) {
377
- $plugin = $details['pro']['plug'];
378
- $details = $details['pro'];
379
- }
380
- }
381
-
382
- if ( array_key_exists( $plugin, $all_plugins ) ) {
383
- if ( is_plugin_active( $plugin ) ) {
384
- // Status text/status.
385
- $plugin_data['status_class'] = 'status-active';
386
- $plugin_data['status_text'] = esc_html__( 'Active', 'custom-facebook-feed' );
387
- // Button text/status.
388
- $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-secondary disabled';
389
- $plugin_data['action_text'] = esc_html__( 'Activated', 'custom-facebook-feed' );
390
- $plugin_data['plugin_src'] = esc_attr( $plugin );
391
- } else {
392
- // Status text/status.
393
- $plugin_data['status_class'] = 'status-inactive';
394
- $plugin_data['status_text'] = esc_html__( 'Inactive', 'custom-facebook-feed' );
395
- // Button text/status.
396
- $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-secondary';
397
- $plugin_data['action_text'] = esc_html__( 'Activate', 'custom-facebook-feed' );
398
- $plugin_data['plugin_src'] = esc_attr( $plugin );
399
- }
400
- } else {
401
- // Doesn't exist, install.
402
- // Status text/status.
403
- $plugin_data['status_class'] = 'status-download';
404
- if ( isset( $details['act'] ) && 'go-to-url' === $details['act'] ) {
405
- $plugin_data['status_class'] = 'status-go-to-url';
406
- }
407
- $plugin_data['status_text'] = esc_html__( 'Not Installed', 'custom-facebook-feed' );
408
- // Button text/status.
409
- $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-primary';
410
- $plugin_data['action_text'] = esc_html__( 'Install Plugin', 'custom-facebook-feed' );
411
- $plugin_data['plugin_src'] = esc_url( $details['url'] );
412
- }
413
-
414
- $plugin_data['details'] = $details;
415
-
416
- return $plugin_data;
417
- }
418
-
419
- /**
420
- * Display the Getting Started tab content.
421
- *
422
- * @since 2.4/5.5
423
- */
424
- protected function output_getting_started() {
425
-
426
- $license = $this->get_license_type();
427
- ?>
428
-
429
- <div class="cff-admin-about-section cff-admin-about-section-first-form" style="display:flex;">
430
-
431
- <div class="cff-admin-about-section-first-form-text">
432
-
433
- <h2>
434
- <?php esc_html_e( 'Creating Your First Feed', 'custom-facebook-feed' ); ?>
435
- </h2>
436
-
437
- <p>
438
- <?php esc_html_e( 'Want to get started creating your first feed with Custom Facebook Feed? By following the step by step instructions in this walkthrough, you can easily publish your first feed on your site.', 'custom-facebook-feed' ); ?>
439
- </p>
440
-
441
- <p>
442
- <?php esc_html_e( 'Navigate to Facebook Feed in the admin sidebar to go the Configure page.', 'custom-facebook-feed' ); ?>
443
- </p>
444
-
445
- <p>
446
- <?php esc_html_e( 'Click on the large blue button to connect your Facebook account.', 'custom-facebook-feed' ); ?>
447
- </p>
448
-
449
- <p>
450
- <?php esc_html_e( 'Once you connect a Facebook account, you can display your feed on any post, page or widget using the shortcode [custom-facebook-feed]. You can also use the Custom Facebook Feed Gutenberg block if your site has the WordPress block editor enabled.', 'custom-facebook-feed' ); ?>
451
- </p>
452
-
453
- <ul class="list-plain">
454
- <li>
455
- <a href="https://smashballoon.com/can-display-feeds-multiple-facebook-pages/?utm_campaign=facebook-free&utm_source=gettingstarted&utm_medium=multiplefeeds" target="_blank" rel="noopener noreferrer">
456
- <?php esc_html_e( 'Display Multiple Feeds', 'custom-facebook-feed' ); ?>
457
- </a>
458
- </li>
459
- <li>
460
- <a href="https://smashballoon.com/using-shortcode-options-customize-facebook-feeds/?utm_campaign=facebook-free&utm_source=gettingstarted&utm_medium=shortcode" target="_blank" rel="noopener noreferrer">
461
- <?php esc_html_e( 'Shortcode Settings Guide', 'custom-facebook-feed' ); ?>
462
- </a>
463
- </li>
464
- <li>
465
- <a href="https://smashballoon.com/find-facebook-page-group-id/?utm_campaign=facebook-free&utm_source=gettingstarted&utm_medium=pageid" target="_blank" rel="noopener noreferrer">
466
- <?php esc_html_e( 'Find My Page ID', 'custom-facebook-feed' ); ?>
467
- </a>
468
- </li>
469
- </ul>
470
-
471
- </div>
472
-
473
- <div class="cff-admin-about-section-first-form-video">
474
- <iframe src="https://www.youtube-nocookie.com/embed/0gykYq3JSrY?rel=0" width="540" height="304" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
475
- </div>
476
-
477
- </div>
478
-
479
- <?php if ( ! in_array( $license, self::$licenses_top, true ) ) { ?>
480
- <div class="cff-admin-about-section cff-admin-about-section-hero">
481
-
482
- <div class="cff-admin-about-section-hero-main">
483
- <h2>
484
- <?php esc_html_e( 'Get Custom Facebook Feed Pro and Unlock all the Powerful Features', 'custom-facebook-feed' ); ?>
485
- </h2>
486
-
487
- <p class="bigger">
488
- <?php
489
- echo wp_kses(
490
- __( 'Thanks for being a loyal Custom Facebook Feed Lite user. <strong>Upgrade to Custom Facebook Feed Pro</strong> to unlock all the awesome features and experience<br>why Custom Facebook Feed is the most popular Facebook feed plugin.', 'custom-facebook-feed' ),
491
- array(
492
- 'br' => array(),
493
- 'strong' => array(),
494
- )
495
- );
496
- ?>
497
- </p>
498
-
499
- <p>
500
- <?php
501
- printf(
502
- wp_kses(
503
- /* translators: %s - stars. */
504
- __( 'We know that you will truly love Custom Facebook Feed. It has over <strong>1000+ five star ratings</strong> (%s) and is active on over 200,000 websites.', 'custom-facebook-feed' ),
505
- array(
506
- 'strong' => array(),
507
- )
508
- ),
509
- '<i class="fa fa-star" aria-hidden="true"></i>' .
510
- '<i class="fa fa-star" aria-hidden="true"></i>' .
511
- '<i class="fa fa-star" aria-hidden="true"></i>' .
512
- '<i class="fa fa-star" aria-hidden="true"></i>' .
513
- '<i class="fa fa-star" aria-hidden="true"></i>'
514
- );
515
- ?>
516
- </p>
517
- </div>
518
-
519
- <div class="cff-admin-about-section-hero-extra">
520
- <div class="cff-admin-columns">
521
- <div class="cff-admin-column-50">
522
- <ul class="list-features list-plain">
523
- <li>
524
- <i class="fa fa-check" aria-hidden="true"></i>
525
- <?php esc_html_e( 'Display photos, videos, and albums in your posts.', 'custom-facebook-feed' ); ?>
526