initial commit

This commit is contained in:
2024-04-29 13:12:44 +05:45
commit 34887303c5
19300 changed files with 5268802 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
# Top 10 - Popular posts plugin for WordPress
[![WordPress Plugin Version](https://img.shields.io/wordpress/plugin/v/top-10.svg?style=flat-square)](https://wordpress.org/plugins/top-10/)
[![License](https://img.shields.io/badge/license-GPL_v2%2B-orange.svg?style=flat-square)](http://opensource.org/licenses/GPL-2.0)
[![WordPress Tested](https://img.shields.io/wordpress/v/top-10.svg?style=flat-square)](https://wordpress.org/plugins/top-10/)
[![Build Status](https://travis-ci.org/WebberZone/top-10.svg?branch=master)](https://travis-ci.org/WebberZone/top-10)
__Requires:__ 5.0
__Tested up to:__ 5.8
__License:__ [GPL-2.0+](http://www.gnu.org/licenses/gpl-2.0.html)
__Plugin page:__ [Top 10](https://webberzone.com/plugins/top-10/) | [WordPress.org plugin page](https://wordpress.org/plugins/top-10/)
Track daily and total visits on your blog posts. Display the count as well as popular and trending posts.
## Description
WordPress doesn't have an in-built system to track page views or displaying popular posts. [Top 10](https://webberzone.com/plugins/top-10/) is an easy to use, yet, powerful WordPress plugin that will count the number of page views of your posts, pages and any custom post types. You can then display the page view counts as well as display your most popular posts.
Top 10 adds two widgets that you can use to display a list of popular posts and the counta cross all your blog posts.
Although several similar plugins exist today, Top 10 is one of the most feature-rich popular post plugins with support for thumbnails, shortcodes, widgets, custom post types and CSS styles. The inbuilt caching system also helps reduce server load by caching your popular posts output. The tracking uses ajax and is thus compatible with most popular caching plugins.
Top 10 also has powerful API and is fully extendable with WordPress actions and filters to allow you easily extend the code base to add new features or tweak existing ones.
### Features
* **Page counter**: Counts page views on single posts, pages and *custom post types* on an hourly basis which can then be easily displayed automatically, using shortcodes or functions
* **Popular posts**: Display a list of popular posts either for total counts or for a custom period. You can choose how many posts are to be displayed along with loads of other customisation options
* **Widget ready**: Sidebar widgets available for daily popular and overall popular posts. Highly customizable widgets to control what you want to display in the list of posts
* **Shortcodes**: The plugin includes two shortcodes `[tptn_list]` and `[tptn_views]` to display the posts list and the number of views respectively
* **Thumbnail support**
* Support for WordPress post thumbnails. Top 10 will create a custom image size (`tptn_thumbnail`) with the dimensions specified in the Settings page
* Auto-extract the first image in your post to be displayed as a thumbnail
* Manually enter the URL of the thumbnail via [WordPress meta fields](http://codex.wordpress.org/Custom_Fields). Specify this using the meta box in your Edit screens.
* **Exclusions**: Exclude posts from select categories from appearing in the top posts list. Also exclude posts by ID from appearing in the list
* **Styles**: The output is wrapped in CSS classes which allows you to easily style the list. You can enter your custom CSS styles from within WordPress Admin area or use the style included.
* **Admin interface**: View list of daily and/or overall popular posts from within the dashboard. Top 10 also adds two sortable columns to your All Posts and All Pages pages in your WordPress Admin area
* **Export/Import interface**: Export the count tables and settings to restore in the same site or on other installs
* **Works with caching plugins** like WP-Super-Cache, W3 Total Cache or Quick Cache
* **Extendable code**: Top 10 has tonnes of filters and actions that allow any developer to easily add features, edit outputs, etc.
### GDPR
Top 10 is GDPR compliant as it doesn't collect any personal data about your visitors when installed out of the box. You can see the data the plugin stores in the `wp_top_ten` and `wp_top_ten_daily` tables in the database. Note: the prefix `wp` might be different if you have changed it from the default.
YOU ARE RESPONSIBLE FOR ENSURING THAT ALL GDPR REQUIREMENTS ARE MET ON YOUR WEBSITE.
### Donations
I spend a significant amount of my free time maintaining, updating and more importantly supporting this plugin. If you have been using this plugin and find this useful, do consider making a donation. This helps me pay for my hosting and domains.
### Translations
Top 10 is available for [translation directly on WordPress.org](https://translate.wordpress.org/projects/wp-plugins/top-10). Check out the official [Translator Handbook](https://make.wordpress.org/polyglots/handbook/rosetta/theme-plugin-directories/) to contribute.
## Screenshots
![Style Options](https://raw.github.com/WebberZone/top-10/master/wporg-assets/screenshot-5.png)
_Top 10 settings page - Styles Options_
For more screenshots visit the [WordPress plugin page](http://wordpress.org/plugins/top-10/screenshots/).
## Installation
### WordPress install (the easy way)
1. Navigate to Plugins within your WordPress Admin Area
2. Click "Add new" and in the search box enter "Top 10"
3. Find the plugin in the list (usually the first result) and click "Install Now"
### Manual install
1. Download the plugin
2. Extract the contents of top-10.zip to wp-content/plugins/ folder. You should get a folder called top-10.
3. Activate the Plugin in WP-Admin.
4. Go to **Top 10 » Settings** to configure
5. Go to **Appearance » Widgets** to add the Popular Posts sidebar widget to your theme
6. Go to **Top 10 » View Popular Posts** to view the list of popular posts
## Frequently Asked Questions
Check out the [FAQ on the plugin page](http://wordpress.org/plugins/top-10/faq/) and the [FAQ on the WebberZone knowledgebase](https://webberzone.com/support/section/top-10/).
If your question isn't listed there, please create a new post at the [WordPress.org support forum](http://wordpress.org/support/plugin/top-10). It is the fastest way to get support as I monitor the forums regularly. I also provide [premium *paid* support via email](https://webberzone.com/support/).
## About this repository
This GitHub repository always holds the latest development version of the plugin. If you're looking for an official WordPress release, you can find this on the [WordPress.org repository](http://wordpress.org/plugins/top-10). In addition to stable releases, latest beta versions are made available under [releases](https://github.com/WebberZone/top-10/releases).

View File

@@ -0,0 +1,594 @@
This file holds the archive of changelog entries
= 2.9.5 =
Release post: [https://webberzone.com/blog/top-10-v2-9-0/](https://webberzone.com/blog/top-10-v2-9-0/)
* Bug fixes:
* Security fix: Nonces were not always checked in import module
= 2.9.4 =
Release post: [https://webberzone.com/blog/top-10-v2-9-0/](https://webberzone.com/blog/top-10-v2-9-0/)
* Bug fixes:
* .json file error when trying to import tables in the Tools page
= 2.9.3 =
Release post: [https://webberzone.com/blog/top-10-v2-9-0/](https://webberzone.com/blog/top-10-v2-9-0/)
* Enhancements:
* Cache now uses MD5 generated keys based on the Top 10 parameters being passed. This means the cache should now work with shortcodes and manual implementations
* Database creation now uses the correct collation
* Bug fixes:
* `include_cat_ids` didn't work with the shortcode
* Password protected posts will no longer show the excerpt
= 2.9.2 =
Release post: [https://webberzone.com/blog/top-10-v2-9-0/](https://webberzone.com/blog/top-10-v2-9-0/)
* Bug fixes:
* Custom CSS box would not save
= 2.9.1 =
Release post: [https://webberzone.com/blog/top-10-v2-9-0/](https://webberzone.com/blog/top-10-v2-9-0/)
* Bug fixes:
* Published age of posts parameter was no longer working
* Importing settings should now work properly - previously checkboxes all ended up being enabled
* In rare cases, the tracker would throw PHP errors e.g. on search results page where no posts were loaded and tracker was enabled to load on all pages
= 2.9.0 =
Release post: [https://webberzone.com/blog/top-10-v2-9-0/](https://webberzone.com/blog/top-10-v2-9-0/)
* Features:
* Edit the total visits from the Top 10 > Popular Posts page
* New shortcode setting `include_cat_ids` to limit top posts to selected categories/taxonomies. Use a comma separated list of [term_taxonomy_id](https://codex.wordpress.org/WordPress_Taxonomy#wp_term_taxonomy)
* New setting in widget to only include certain categories. Doesn't work with custom taxonomies
* Enhancements:
* Implemented CodeMirror to format custom styles box
* Admin scripts are no longer loaded into the head - but using a separate JavaScript file
* Bug fixes:
* Fixed media lookup returning PHP errors/warnings in rare cases
* Use `current_time` and `gmdate` as per latest WordPress Coding Standards
* No more unnecessary form modified errors in the popular posts tables in Admin area
* Fixed notices in PHP 7.4 when viewing popular posts listings
* When editing posts, the count from the metabox will only be used if it is modified
= 2.8.0 =
Release post: [https://webberzone.com/blog/top-10-v2-8-0/](https://webberzone.com/blog/top-10-v2-8-0/)
* Features:
* Custom feed for popular posts: Find new options under a new tab called Feed in the settings page where you can set the URL for the overall and daily feeds
* New page in the network admin menu to view the popular posts across the network
* Also delete transients and other settings on uninstall
= 2.7.0 =
Release post: [https://webberzone.com/blog/top-10-v2-7-0/](https://webberzone.com/blog/top-10-v2-7-0/)
* Features:
* Recreate the Top 10 database tables. You can find the button in the Tools page. Backup your database first
* New export/import interface to export and import the Top 10 tables and settings
* Enhancements:
* `tptn_views` shortcode adds a new parameter 'count' to explicitly set the count type. Choose from daily, total or overall. This is overridden if daily is set to 0 (backwards compatibility)
= 2.6.3 =
* Enhancements:
* `tptn_get_first_image` filter has additional attributes `$image_attributes[0], $postid, $thumb_width, $thumb_height`
* Bug fixes:
* Reverted PolyLang implementation that was broken in v2.6.2
* Delete deprecated settings on save
* Fix settings link in plugins listing page
* Fix exclude categories setting on save
= 2.6.2 =
* Enhancements:
* Select a date range in the Popular Posts listing page in the admin
* Bug fixes:
* Fixed "Published post date" setting was not working. Thanks [@jherrerai](https://github.com/jherrerai)
* Modified PolyLang and WPML function implementations
= 2.6.1 =
* Bug fixes:
* Fixed widget daily and hourly range not working which was broken in v2.6.0
= 2.6.0 =
* Features:
* New option to disable creation of image thumbnails. Find this under Thumbnail options
* Thumbnail HTML markup includes `srcset` and `sizes` attributes when available. Read [Responsive Images in WordPress 4.4](https://make.wordpress.org/core/2015/11/10/responsive-images-in-wordpress-4-4/)
* New option to turn on debug mode. You can turn this on when requesting support. Find it under the Counter/Tracker tab
* New option to add the tracker js file on all pages, not just singular pages. Helps with minification/concatenation
* New date filter in the Popular posts listing page to see the views on a particular date
* New option to turn ON/OFF the number formatting of the post counts. ON by default
* Enhancements:
* Load tracker in footer
* Renamed top-10-tracker.js to top-10-tracker.min.js
* Bug fixes:
* Only delete option if null value is passed to tptn_update_option
* "Exclude display on these post IDs" moved under Counter section
= 2.5.7 =
* Enhancements:
* Tools page now has the code to Recreate the PRIMARY KEY in case the button gives an error. You will need to run this in phpMyAdmin or Adminer
* Bug fixes:
* Fixed translation of " by " which had the incorrect text domain
* Post types to includes selects "post" in case no option is selected
* Unchecking all boxes of a "Display number of views on" setting would sometimes pick the default value
= 2.5.6 =
* Features:
* Added new button under Tools to recreate the PRIMARY KEYs
= 2.5.5 =
* Bug fixes:
* Fixed missing semi-colon in tracker code
* Multi-site tracking failed in old installs where the PRIMARY KEY was not properly updated in the database. DB version has been updated to 6.0 to initiate primary key across all installs
= 2.5.4 =
* Features:
* New button in the Tools page to delete the pre-2.5.x settings
* Enhancements:
* New function `tptn_trim_char` replaces `tptn_max_formatted_content` which should now support non-English characters as well
* Counts in the "Popular Posts" page are now number formatted
* Bug fixes:
* Fixed PHP Illegal string offset error
= 2.5.3 =
* Bug fixes:
* Fixed number of posts displayed in the popular posts list
= 2.5.2 =
* Bug fixes:
* Settings / Thumbnail / Thumbnail size did not display the correct option even though the admin had this correctly saved
= 2.5.1 =
* Bug fixes:
* Custom CSS did not get upgraded or saved properly
* Uninstalling the plugin will delete the settings properly
= 2.5.0 =
* Features:
* Upgrade old options to Settings API
* New widget to display the overall count i.e. visits across all your site posts
* Added a filter to override the number of days that maintenance considers to delete the database entries
* New option to disable tracking for logged in users. Find "Track logged-in users" under the "Counter/Tracker" tab in the settings screen
* Enhancements:
* Make $ajax_tptn_tracker global. Contributed by [@pkirk](https://github.com/pkirk)
* Bug fixes:
* Make sure that $post object is available in `tptn_pc_content` filter. Contributed by [@mtws](https://github.com/mtws)
* When editing Attachment post types, metabox should now save correctly
* Disable `top_ten_nonce` as it wasn't needed for front-end users and conflicted with caching plugins
* Deprecated:
* `tptn_default_options` (no replacement) and `tptn_read_options` (Use `tptn_get_settings` instead)
= 2.4.4 =
* Enhancements:
* Changed tracker type to Query based for better compatibility
* Bug fixes:
* Security fix: Potential SQL injection vulnerability. Reported by [DefenseCode ThunderScan](http://www.defensecode.com/)
* Revisions no longer displayed in the "View Popular Posts" screen in admin area
= 2.4.3 =
* Bug fixes:
* Fatal error when running PHP 7.1.x
= 2.4.2 =
* Bug fixes:
* The plugin will no longer generate any notices if post author is missing
* Fixed T_FUNCTION error in admin area on blogs running on PHP versions before 5.3
* Fixed bug where any special characters in the post title would break the output
= 2.4.1 =
* Bug fixes:
* Fixes fatal error caused on installs which have versions below PHP5.6
= 2.4.0 =
* Features:
* New tracker using a properly enqueued `.js` file. Two inbuilt options to use query variables or ajaxurl to process the counts
* Shortcode and the widget now have an added parameter for 'offset'. This is useful if you would like to display different widgets/shortcodes but not always start from the first post
* Bug fixes:
* Attachments now work with the widget and elsewhere
* New tracker now works when jQuery is loaded in the footer
* Don't add tracker code when previewing in customizer
* Doesn't report an error if no author is assigned to a post
* Deprecated:
* `tptn_add_tracker` and `tptn_add_viewed_count` have been deprecated. These should no longer be needed with the new tracker option.
* wick script in Settings page which was used for fetching category slugs. You should now use the category name (prompted automatically). Slugs will be automatically converted into names.
= 2.3.2 =
* Bug fixes:
* Sanitized several unsanitized post and get requests
* Deprecated:
* External PHP file tracking option introduced in v2.3.0 in line with wordpress.org plugin repository listing requirements.
= 2.3.1 =
* Bug fixes:
* Potential CSRF issue fixed in admin area
= 2.3.0 =
* Features:
* Preliminary support for PolyLang
* Search box and post type filter added in Admin » View Popular Posts screen
* Link to Daily Popular posts screen under Top 10 menu in admin area
* `post_types` parameter now supports comma-separated list of post types. To fetch all built-in post types use 'all'
* New option to use the external and more efficient javascript file for tracking
* New function `tptn_add_tracker` to manually include the tracking code. This is useful if your theme doesn't have `the_content` function that Top 10 filters to add the tracker code
* Enhancements:
* Viewing drafts will no longer increment the counter
* When using the Left Thumbs style, each widget instance includes the CSS code to display the correct thumbnail size
* Bug fixes:
* Missing `DISTINCT` keyword in query resulting in duplicate entries in some cases
* PHP Notice in Widget on empty search and 404 pages
* Incorrect notice that Contextual Related Posts is installed on Edit Posts pages
* `tptn_show_daily_pop_posts()` without arguments did not display daily posts
* Using Exclude categories returned incorrect counts and excluded non-posts
* Incorrect count on the Admin » View Popular Posts screen causing incorrect pagination
* Incorrect thumbnail size being pulled out in some instances
* Multiple widget instances incorrectly used the same cache
* Incorrect text domain was initialised
= 2.2.4 =
* Enhancements:
* Changed text domain to `top-10` in advance of translate.wordpress.org translation system
* Improved support for WPML. If available, same language posts will be pulled by default. To restrict to the same language [add this code](https://gist.github.com/ajaydsouza/9b1bc56cec79295e784c) to your theme's functions.php file
= 2.2.3 =
* Bug fixes:
* Shortcode with "exclude_categories" argument works again
= 2.2.2 =
* Bug fixes:
* Fixed array declaration to support PHP < 5.4
= 2.2.0 =
* Features:
* Caching system using the Transients API. By default the cache is refreshed every hour
* Styles interface lets you select between No styles, Left Thumbs (previously the default style) and Text Only
* Option to limit posts only with a specified date range
* Option in Top 10 meta box to exclude display of popular posts in widget if needed
* Option in Top 10 meta box to exclude post from popular posts list
* Cleaner interface to view popular posts in the admin area
* Enhancements:
* `strict_limit` is true by default for `get_tptn_pop_posts()`
* Option to turn off the meta box for everyone or just non-admins
* Contributors & above can also update the visit count in the meta box if this is enabled for them
* Category exclusion now works via a filter function vs. multiple lookups, thereby reducing the number of database queries
* Bug fixes:
* Potential bug when the $wp variable was not detected in rare situations
* In rare cases category exclusion failed when `term_id` didn't match `term_taxonomy_id`
* Deprecated:
* `ald_tptn_rss`: Use `tptn_rss_filter` instead
* `ald_tptn_hook` deprecated and renamed to `tptn_cron_hook`
* `tptn_manage` and `tptn_manage_daily` which were used to render the admin popular posts screens
= 2.1.0 =
* Features:
* New: Button in Top 10 settings page to merge posts across blog ID 0 and 1
* New: Function & filter `get_tptn_pop_posts` that can be used to fetch the popular posts as an object or array. Perfect if you want to write custom code in your theme
* New: Support for WPML to return the correct language ID. Thanks to Tony Flags' <a href="https://wordpress.org/support/topic/top-10-and-languages-in-wpml?replies=11#post-6622085">code snippet</a>.
* New: Filter `tptn_list_count` to modify the formatted list count. See a <a href="https://gist.github.com/ajaydsouza/9f04c26814414a57fab4">working example</a>
* New: Post types can now be selected in the widget. This allows you to select top posts by post type
* Enhancements:
* Modified: Plugin will attempt to pull the correct size image when fetching the first image in a post
* Modified: Deprecated "Always display latest post count in the daily lists"
* Modified: timthumb has been deprecated. The script is no longer packaged within Top 10
* Bug fixes:
* Fixed: Bug in tracking code when not using Ajax
* Fixed: Bug in admin column did not check for the blog_id
* Fixed: Bug where default thumbnail location was not correctly saved
* Fixed: Incorrect thumbnail was pulled on attachment pages
* Fixed: blog_id column of the database is correctly initialised as `DEFAULT '1'`
= 2.0.3 =
* Features:
* New: Options to choose if you want to delete the Top 10 options and/or data when deleting the plugin
* Bug fixes:
* Fixed: Metabox update did not work properly in v2.0
* Fixed: Duplicate include files
* Modified: In the mySQL tables, the blog_id default value is set to 1
= 2.0.2 =
* Features:
* New: Option to display the daily posts count from midnight. This is enabled by default and mimics the original behaviour of the counter in Top 10 v1.x
* Enhancements:
* Modified: Posts are tracked hourly based on the time of the blog and not GMT. This was also the default behaviour of the counter in Top 10 v1.x
* Bug fixes:
* Fixed: Default thumbnail location saved correctly on the Settings page.
= 2.0.1 =
* Bug fixes
* 500/503 errors caused by 2.0.0
= 2.0.0 =
* Features:
* New: Multisite support. If you're using multisite and have previously activated Top 10 on individual blogs in the network, then head over to **Top 10 Settings** and import the counts from the old Top 10 1.x tables to the new Top 10 v2.0 tables
* New: Fully extendable lookup query for the top lists. Now you can create your own functions in functions.php or in addon plugins to modify the mySQL query
* New: Option to use any of the inbuilt thumbnail sizes or create your own custom image size. If a custom size is chosen, then the plugin uses `add_image_size` to register the custom size. You will need to resize your thumbnails after activating this option
* New: Actions and filters in the Top 10 Settings page and in the widget which allows for addons to add more settings
* Enhancements:
* Modified: Post tracking is now done on an hourly basis. Date limiting is also on an hourly basis. So, 1 day is actually the last 24 hours and not from midnight anymore!
* Modified: Update and View counts now use query variables instead of external JavaScript files. Check http://goo.gl/yemvyM for sample functions to restore the old method
* Modified: Activating the default styles option will automatically set the thumbnail width and height to 65px, disable author and excerpt and enable crop mode for the thumbnails
* Bug fixes:
* Fixed: Fix schedule overwrite for the cron job
* Fixed: Incorrect permission lookup in the metabox
= 1.9.10.2 =
* Fixed: Schedules were overwritten when activating the maintenance cron job
= 1.9.10.1 =
* Fixed: Initialisation error for new installs
= 1.9.10 =
* New: Meta box on Edit post / page and similar screens that allow you to set the Top 10 (and my other plugins) specific thumbnail for the current post (different from the Featured thumb)
* New: Admins can edit the number of total views (find it in the same meta box as above)
* New: Turn of tracking for Editors
* New: Added w.org and github.com to list of allowed sites for timthumb
* New: Option to add quality settings for thumbnails created by timthumb
* Modified: Shortcode now accepts all the parameters that `tptn_pop_posts()` can take. For a full list of parameters, please check out the FAQ.
* Modified: Widget initialisation to latest standards
* Fixed: Localisation initialisation
* Fixed: Validation for hour and minute settings for the cron job
* New: Several new filters allowing you to hook in an modify the output without editting plugin files
* Modified: Reformatted code
= 1.9.9.2 =
* Fixed: Show count in widget was always checked
* Fixed: "List of post or page IDs to exclude from the results" did not work for more than one post
* Fixed: First image in the post was not detected in some cases. First image attached is now prioritised over image detection to speed things up
= 1.9.9.1 =
* Fixed: Maintenance cron wasn't running properly
= 1.9.9 =
* New: Default style to make those popular posts a little pretty. Choose **Thumbnails inline, before title** under 'Thumbnail options'
* New: Option to disable display of counts to non-admins. Check out the option 'Show number of views to non-admins'
* New: Option to display different text when there are no hits on the post on non single posts e.g. home page, archives, etc.
* New: Class `tptn_posts_widget` for the widgets
* Modified: Brought back the old columns "Views" in the Admin Posts and Pages which contains both the Overall and Daily counts
* Modified: New admin interface keeping mobile first in mind
* Modified: Optimised widgets loading
* Modified: Cron job will now delete entries from the daily table older than 90 days
* Fixed: mySQL error messages due to improper escaping
* Fixed: Plugin no longer overwrites cron schedules
* Modified: Lot's of code optimisation and cleanup
= 1.9.8.5 =
* Modified: Including the author in the list will now use the Display Name which is set under “Display name publicly as” in the User Profile page
* Fixed: If the Thumbnail meta field is omitted under Output Options, the plugin will automatically revert to its default value i.e. "post-image"
* Modified: Cleaner pagination when viewing the Top posts in the Admin section
* New: Function `get_tptn_post_count_only` to get just the post count. Use it by passing the Post ID and the type of count (total, daily or overall): `get_tptn_post_count_only($id = FALSE, $count = 'total')`
* New: Class `tptn_after_thumb` that wraps around all items of the list after the post thumbnail. This allows you to cleanly style all items to float to the right of the thumbnail
* Modified: Updated timthumb
= 1.9.8.4 =
* Fixed PHP notices on Admin pages
= 1.9.8.3 =
* Fixed: Daily count was selecting an extra date when using the widget
* Fixed: Default settings for the widget weren't initiated correctly in some cases
* Modified: Admin columns of Total and Daily views will be sorted by descending order by default. Click again to sort in ascending order
* Modified: Admin columns are fixed to 100px width by default instead of `auto`.
= 1.9.8.2 =
* New: Option to add author
* New: More options for the Widgets to configure the post lists
* Modified: Shortcodes are now stripped from excerpts
* New: Added *s3.amazonaws.com* to list of allowed sites that timthumb can fetch images from
* Fixed: Counter was not always displayed on posts
* New: All Posts / All Pages have separate *sortable* columns for total and daily counts
* Fixed: Warning messages with WP_DEBUG mode ON
= 1.9.8.1 =
* Fixed: Correct numbers of posts were not being fetched
= 1.9.8 =
* New: Custom post support. Choose which custom post types to display in the top posts
* New: More display options. Select which archives you want to display the post count
* New: Option to open links in new window
* New: Option to add nofollow attribute to links
* New: Option to exclude posts by ID in the list of top posts being displayed
* New: Option to prevent display of the Visit Count on posts by ID
* New: Option to choose between using CSS styles or HTML attributes for thumbnail width and height. *HTML width and height attributes are default*
* New: Option to restrict the title to fixed number of characters
* New: Option to add the date to the list
* Modified: Numbers are now formatted based on the locale
* Fixed: Plugin will now create thumbnails from the first image in gallery custom posts
= 1.9.7 =
* New: Option to toggle using jQuery ON to track counts. Potential fix for counters not working.
= 1.9.6 =
* Fixed: Daily count was not updated
= 1.9.5 =
* New: CSS class `tptn_title` that can be used to style the title of the posts
* New: Option to disable Daily or Overall counters
* Fixed: Counter to work with different directory structures. *Thanks Nathan for the fix*
* Fixed: To make it work with W3 Total Cache. *Thanks Angelo for the fix*
* Modified: timthumb will now work if you have JetPack Proton activated
= 1.9.4 =
* Fixes a bug in the widget introduces in 1.9.3
= 1.9.3 =
* Important security update: Fixed possible XSS vulnerability
* Fixed: Exclude categories was not excluding posts correctly
* New: Classes `tptn_posts` and `tptn_posts_daily` for the widgets that let you easily style the lists
= 1.9.2 =
* New: Top 10 now has its own menu in the administration area. Access settings and view your top posts directly under the new menu: "Top 10"
* New: New classes **tptn_counter** and **tptn_list_count** to style the displayed count
* New: New option "Always display latest count for the post" to not use JavaScript to display the counts for a post. This speeds up since no external JS file is used to display the count. Ideal for those not using caching plugins or are not particularly worried if the counts are slightly older.
* Fixed: PHP notices when WP_DEBUG is turned on
* Modified: Updated timthumb.php
= 1.9.1 =
* Fixed: Plugin will now only reschedule the cron job if there any settings are changed related to it
* Modified: If timthumb is disabled, WordPress post thumbnails are no longer resized using timthumb
* Modified: Extra check for post featured thumbnails to ensure that the src is not missed
= 1.9 =
* New: Option to use timthumb to resize thumbnails
* New: New variable **%overallcount%** that will display the total pageviews on the blog across all posts
* New: Post thumbnails are now properly resized based on width and height settings in the Top 10 settings page
* New: Customise what to display when there are no top posts detected
* New: New scheduled maintenance to clear up daily tables and optimise performance
* New: Custom CSS code to style the output. Check out the available styles in the <a href="http://wordpress.org/extend/plugins/top-10/faq/">FAQ</a>.
* Modified: New "default.png" file based on from KDEs <a href="http://www.oxygen-icons.org/">Oxygen icon set</a>
* Modified: Dashboard list of posts now displays all the top posts and pages instead of the filtered list based on Settings.
* Modified: Dashboard widget now has options to customise the widget. Old widgets have been deleted
* Modified: When fetching the first image, plugin ignores external images
* Modified: Minor performance tweaks
= 1.8.1 =
* Fixed: Dashboard widgets linking
= 1.8 =
* New: Support for <a href="https://wordpress.org/extend/plugins/video-thumbnails/">Video Thumbnails</a> plugin
* New: Thumbnail settings now reflect max width and max height instead of fixed width and height
* New: Option to display thumbnails before or after the title
* New: Option to not display thumbnails instead of the default thumbnail
* New: Counts are now neatly formatted with commas
* Modified: Minor tweaks to improve performance
= 1.7.6 =
* Fixed: Bug with Daily posts widget created an extra header tag in certain themes
= 1.7.5 =
* New: Now supports multiple WordPress widgets
= 1.7 =
* New: Exclude posts in the top lists from select categories
* Modified: Performance improvements
* Modified: Better compatibility with the latest versions of WordPress. If you are using the sidebar widgets, please readd them to your theme under Appearance > Widgets
= 1.6.3 =
* Fixed: PHP errors on certain installs
* New: Dutch language
= 1.6.2 =
* Fixed: Multiple rows being created for same ID
* Fixed: Counter display
* New: New button to clear the duplicate rows in the tables
* Fixed: Top 10 should be lighter on the server now
= 1.6.1 =
* Turned the credit option to false by default. This setting won't effect current users.
* Turned off borders on post thumbnails. You can customise the CSS class "tptn_thumb" to style the post thumbnail.
* The plugin will now display a list of changes in the WordPress Admin > Plugins area whenever an update is available
* Fixed: Display of caching plugin compliant daily top posts lists
= 1.6 =
* New: Added support for excerpts and detection of first image in the post
* New: Daily posts are tracked using the blog time instead of server time
* Fixed: On the first visit, display 1 instead of 0
* Fixed: Fixed uninstall script
= 1.5.3 =
* New: You can now use HTML in the counter display
= 1.5.2 =
* Fixed: Fixed display of post thumbnails using postmeta field
= 1.5.1 =
* Fixed some compatibility issues with WordPress 2.9 and YARPP
= 1.5 =
* Added support for post thumbnails feature of WordPress 2.9
= 1.4.1 =
* Fixed compatibility with WordPress 2.9
* Fixed XHTML validation errors in output code
* Added buttons to reset post count of overall and daily posts
= 1.4 =
* Added localisation support
* Separate options to display number of views on posts and pages
= 1.3 =
* "Daily Popular" can now be selected over user selectable number of days.
* Option to turn off display of number of pageviews in popular posts list
* Option to make "Daily Popular" list compatible with caching plugins
* Posts > Top 10 page to view detailed list of popular posts
= 1.2 =
* Do not display Drafts in Related Posts anymore
* Option to disable tracking author visits on their own posts
* Display top posts for the current day
= 1.1 =
* Added the Popular Posts sidebar widget in your theme. Find it under <strong>Appearance > Widgets</strong>
* Uses JavaScript by default to count. Hence, better support for different caching plugins
* Change format to display count. Now, a single textarea instead of two text boxes.
* Added WordPress 2.7 Dashboard widget to display popular posts on your Dashboard
= 1.0.1 =
* Release

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,63 @@
.tptn_posts_daily ul, .tptn_posts ul {
margin:0 !important;
padding:0 !important;
}
.tptn_posts_daily ul li, .tptn_posts ul li {
clear:both;
list-style:none;
margin-bottom:15px;
display:block;
background: none;
padding:0 !important;
}
.tptn_posts_daily ul:after, .tptn_posts ul:after, .tptn_posts_daily ul li:after, .tptn_posts ul li:after {
content:'';
display:table;
clear: both;
}
.tptn_posts_daily .tptn_title, .tptn_posts .tptn_title {
font-weight:bold;
display:block;
padding-bottom:5px;
text-decoration:none;
line-height: 1.1em;
}
img.tptn_thumb {
display:block;
float:left;
clear:left;
margin-right:10px !important;
padding:3px !important;
border:1px #CCCCCC solid;
vertical-align: bottom;
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,.4);
-moz-box-shadow: 0 1px 2px rgba(0,0,0,.4);
box-shadow: 0 1px 2px rgba(0,0,0,.4);
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
}
img.tptn_thumb:after {
content: ' ';
width: 100%;
height: 100%;
position: absolute;
top: -1px;
left: -1px;
border: solid 1px #222;
-webkit-box-shadow: inset 0 0 1px rgba(255,255,255,.4), inset 0 1px 0 rgba(255,255,255,.4), 0 1px 2px rgba(0,0,0,.3);
-moz-box-shadow: inset 0 0 1px rgba(255,255,255,.4), inset 0 1px 0 rgba(255,255,255,.4), 0 1px 2px rgba(0,0,0,.3);
box-shadow: inset 0 0 1px rgba(255,255,255,.4), inset 0 1px 0 rgba(255,255,255,.4), 0 1px 2px rgba(0,0,0,.3);
-webkit-border-radius: 7px;
-moz-border-radius: 7px;
border-radius: 7px;
}
.tptn_excerpt {
display: block;
}

View File

@@ -0,0 +1 @@
.tptn_posts ul,.tptn_posts_daily ul{margin:0!important;padding:0!important}.tptn_posts ul li,.tptn_posts_daily ul li{clear:both;list-style:none;margin-bottom:15px;display:block;background:0 0;padding:0!important}.tptn_posts ul li:after,.tptn_posts ul:after,.tptn_posts_daily ul li:after,.tptn_posts_daily ul:after{content:'';display:table;clear:both}.tptn_posts .tptn_title,.tptn_posts_daily .tptn_title{font-weight:700;display:block;padding-bottom:5px;text-decoration:none;line-height:1.1em}img.tptn_thumb{display:block;float:left;clear:left;margin-right:10px!important;padding:3px!important;border:1px #ccc solid;vertical-align:bottom;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.4);-moz-box-shadow:0 1px 2px rgba(0,0,0,.4);box-shadow:0 1px 2px rgba(0,0,0,.4);-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}img.tptn_thumb:after{content:' ';width:100%;height:100%;position:absolute;top:-1px;left:-1px;border:solid 1px #222;-webkit-box-shadow:inset 0 0 1px rgba(255,255,255,.4),inset 0 1px 0 rgba(255,255,255,.4),0 1px 2px rgba(0,0,0,.3);-moz-box-shadow:inset 0 0 1px rgba(255,255,255,.4),inset 0 1px 0 rgba(255,255,255,.4),0 1px 2px rgba(0,0,0,.3);box-shadow:inset 0 0 1px rgba(255,255,255,.4),inset 0 1px 0 rgba(255,255,255,.4),0 1px 2px rgba(0,0,0,.3);-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px}.tptn_excerpt{display:block}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1,176 @@
<?php
/**
* Functions run on activation / deactivation.
*
* @package Top_Ten
*/
/**
* Fired when the plugin is Network Activated.
*
* @since 1.9.10.1
*
* @param boolean $network_wide True if WPMU superadmin uses
* "Network Activate" action, false if
* WPMU is disabled or plugin is
* activated on an individual blog.
*/
function tptn_activation_hook( $network_wide ) {
global $wpdb;
if ( is_multisite() && $network_wide ) {
// Get all blogs in the network and activate plugin on each one.
$blog_ids = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
"
SELECT blog_id FROM $wpdb->blogs
WHERE archived = '0' AND spam = '0' AND deleted = '0'
"
);
foreach ( $blog_ids as $blog_id ) {
switch_to_blog( $blog_id );
tptn_single_activate();
}
// Switch back to the current blog.
restore_current_blog();
} else {
tptn_single_activate();
}
}
register_activation_hook( TOP_TEN_PLUGIN_FILE, 'tptn_activation_hook' );
/**
* Fired for each blog when the plugin is activated.
*
* @since 2.0.0
*/
function tptn_single_activate() {
global $wpdb, $tptn_db_version;
$tptn_settings = tptn_get_settings();
$charset_collate = $wpdb->get_charset_collate();
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$table_name = $wpdb->base_prefix . 'top_ten';
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
if ( $wpdb->get_var( "show tables like '$table_name'" ) != $table_name ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$sql = 'CREATE TABLE ' . $table_name . // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
" (
postnumber bigint(20) NOT NULL,
cntaccess bigint(20) NOT NULL,
blog_id bigint(20) NOT NULL DEFAULT '1',
PRIMARY KEY (postnumber, blog_id)
) $charset_collate;";
dbDelta( $sql );
}
if ( $wpdb->get_var( "show tables like '$table_name_daily'" ) != $table_name_daily ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$sql = 'CREATE TABLE ' . $table_name_daily . // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange
" (
postnumber bigint(20) NOT NULL,
cntaccess bigint(20) NOT NULL,
dp_date DATETIME NOT NULL,
blog_id bigint(20) NOT NULL DEFAULT '1',
PRIMARY KEY (postnumber, dp_date, blog_id)
) $charset_collate;";
dbDelta( $sql );
}
add_site_option( 'tptn_db_version', $tptn_db_version );
// Upgrade table code.
$installed_ver = get_site_option( 'tptn_db_version' );
if ( $installed_ver != $tptn_db_version ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$sql = 'ALTER TABLE ' . $table_name . ' DROP PRIMARY KEY ';
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$sql = 'ALTER TABLE ' . $table_name_daily . ' DROP PRIMARY KEY ';
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$sql = 'CREATE TABLE ' . $table_name . " (
postnumber bigint(20) NOT NULL,
cntaccess bigint(20) NOT NULL,
blog_id bigint(20) NOT NULL DEFAULT '1',
PRIMARY KEY (postnumber, blog_id)
) $charset_collate;";
$sql .= 'CREATE TABLE ' . $table_name_daily . " (
postnumber bigint(20) NOT NULL,
cntaccess bigint(20) NOT NULL,
dp_date DATETIME NOT NULL,
blog_id bigint(20) NOT NULL DEFAULT '1',
PRIMARY KEY (postnumber, dp_date, blog_id)
) $charset_collate;";
dbDelta( $sql );
update_site_option( 'tptn_db_version', $tptn_db_version );
}
}
/**
* Fired when a new site is activated with a WPMU environment.
*
* @since 2.0.0
*
* @param int $blog_id ID of the new blog.
*/
function tptn_activate_new_site( $blog_id ) {
if ( 1 !== did_action( 'wpmu_new_blog' ) ) {
return;
}
switch_to_blog( $blog_id );
tptn_single_activate();
restore_current_blog();
}
add_action( 'wpmu_new_blog', 'tptn_activate_new_site' );
/**
* Fired when a site is deleted in a WPMU environment.
*
* @since 2.0.0
*
* @param array $tables Tables in the blog.
*/
function tptn_on_delete_blog( $tables ) {
global $wpdb;
$tables[] = $wpdb->prefix . 'top_ten';
$tables[] = $wpdb->prefix . 'top_ten_daily';
return $tables;
}
add_filter( 'wpmu_drop_tables', 'tptn_on_delete_blog' );
/**
* Function to call install function if needed.
*
* @since 1.9
*/
function tptn_update_db_check() {
global $tptn_db_version, $network_wide;
if ( get_site_option( 'tptn_db_version' ) != $tptn_db_version ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
tptn_activation_hook( $network_wide );
}
}
add_action( 'plugins_loaded', 'tptn_update_db_check' );

View File

@@ -0,0 +1,162 @@
<?php
/**
* Manage columns on All Posts and All pages screens.
*
* @package Top_Ten
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Add an extra column to the All Posts page to display the page views.
*
* @since 1.2
*
* @param array $cols Array of all columns on posts page.
* @return array Modified array of columns.
*/
function tptn_column( $cols ) {
if ( ( current_user_can( 'manage_options' ) ) || ( tptn_get_option( 'show_count_non_admins' ) ) ) {
if ( tptn_get_option( 'pv_in_admin' ) ) {
$cols['tptn_total'] = __( 'Total Views', 'top-10' );
$cols['tptn_daily'] = __( "Today's Views", 'top-10' );
$cols['tptn_both'] = __( 'Views', 'top-10' );
}
}
return $cols;
}
add_filter( 'manage_posts_columns', 'tptn_column' );
add_filter( 'manage_pages_columns', 'tptn_column' );
/**
* Display page views for each column.
*
* @since 1.2
*
* @param string $column_name Name of the column.
* @param int|string $id Post ID.
*/
function tptn_value( $column_name, $id ) {
global $wpdb;
$blog_id = get_current_blog_id();
// Add Total count.
if ( ( 'tptn_total' === $column_name ) && ( tptn_get_option( 'pv_in_admin' ) ) ) {
$table_name = $wpdb->base_prefix . 'top_ten';
$resultscount = $wpdb->get_row( $wpdb->prepare( "SELECT postnumber, cntaccess FROM {$table_name} WHERE postnumber = %d AND blog_id = %d ", $id, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$cntaccess = tptn_number_format_i18n( ( ( $resultscount ) ? $resultscount->cntaccess : 0 ) );
echo esc_html( $cntaccess );
}
// Now process daily count.
if ( ( 'tptn_daily' === $column_name ) && ( tptn_get_option( 'pv_in_admin' ) ) ) {
$table_name = $wpdb->base_prefix . 'top_ten_daily';
$from_date = tptn_get_from_date();
$resultscount = $wpdb->get_row( $wpdb->prepare( "SELECT postnumber, SUM(cntaccess) as visits FROM {$table_name} WHERE postnumber = %d AND dp_date >= %s AND blog_id = %d GROUP BY postnumber ", $id, $from_date, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$cntaccess = tptn_number_format_i18n( ( ( $resultscount ) ? $resultscount->visits : 0 ) );
echo esc_html( $cntaccess );
}
// Now process both.
if ( ( 'tptn_both' === $column_name ) && ( tptn_get_option( 'pv_in_admin' ) ) ) {
$table_name = $wpdb->base_prefix . 'top_ten';
$resultscount = $wpdb->get_row( $wpdb->prepare( "SELECT postnumber, cntaccess FROM {$table_name} WHERE postnumber = %d AND blog_id = %d ", $id, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$cntaccess = tptn_number_format_i18n( ( ( $resultscount ) ? $resultscount->cntaccess : 0 ) );
$table_name = $wpdb->base_prefix . 'top_ten_daily';
$from_date = tptn_get_from_date();
$resultscount = $wpdb->get_row( $wpdb->prepare( "SELECT postnumber, SUM(cntaccess) as visits FROM {$table_name} WHERE postnumber = %d AND dp_date >= %s AND blog_id = %d GROUP BY postnumber ", $id, $from_date, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$cntaccess .= ' / ' . tptn_number_format_i18n( ( ( $resultscount ) ? $resultscount->visits : 0 ) );
echo esc_html( $cntaccess );
}
}
add_action( 'manage_posts_custom_column', 'tptn_value', 10, 2 );
add_action( 'manage_pages_custom_column', 'tptn_value', 10, 2 );
/**
* Register the columns as sortable.
*
* @since 1.9.8.2
*
* @param array $cols Array with column names.
* @return array Filtered columns array
*/
function tptn_column_register_sortable( $cols ) {
if ( tptn_get_option( 'pv_in_admin' ) ) {
$cols['tptn_total'] = array( 'tptn_total', true );
$cols['tptn_daily'] = array( 'tptn_daily', true );
}
return $cols;
}
add_filter( 'manage_edit-post_sortable_columns', 'tptn_column_register_sortable' );
add_filter( 'manage_edit-page_sortable_columns', 'tptn_column_register_sortable' );
/**
* Add custom post clauses to sort the columns.
*
* @since 1.9.8.2
*
* @param array $clauses Lookup clauses.
* @param object $wp_query WP Query object.
* @return array Filtered clauses
*/
function tptn_column_clauses( $clauses, $wp_query ) {
global $wpdb;
if ( isset( $wp_query->query['orderby'] ) && 'tptn_total' === $wp_query->query['orderby'] ) {
$table_name = $wpdb->base_prefix . 'top_ten';
$clauses['join'] .= "LEFT OUTER JOIN {$table_name} ON {$wpdb->posts}.ID={$table_name}.postnumber";
$clauses['orderby'] = 'cntaccess ';
$clauses['orderby'] .= ( 'ASC' === strtoupper( $wp_query->get( 'order' ) ) ) ? 'ASC' : 'DESC';
}
if ( isset( $wp_query->query['orderby'] ) && 'tptn_daily' === $wp_query->query['orderby'] ) {
$table_name = $wpdb->base_prefix . 'top_ten_daily';
$from_date = tptn_get_from_date();
$clauses['join'] .= "LEFT OUTER JOIN {$table_name} ON {$wpdb->posts}.ID={$table_name}.postnumber";
$clauses['where'] .= " AND {$table_name}.dp_date >= '$from_date' ";
$clauses['groupby'] = "{$table_name}.postnumber";
$clauses['orderby'] = "SUM({$table_name}.cntaccess) ";
$clauses['orderby'] .= ( 'ASC' === strtoupper( $wp_query->get( 'order' ) ) ) ? 'ASC' : 'DESC';
}
return $clauses;
}
add_filter( 'posts_clauses', 'tptn_column_clauses', 10, 2 );
/**
* Output CSS for width of new column.
*
* @since 1.2
*/
function tptn_admin_css() {
?>
<style type="text/css">
#tptn_total, #tptn_daily, #tptn_both { max-width: 100px; }
</style>
<?php
}
add_action( 'admin_head', 'tptn_admin_css' );

View File

@@ -0,0 +1,132 @@
<?php
/**
* Top 10 Dashboard display.
*
* Functions to add the popular lists to the WordPress Admin Dashboard
*
* @package Top_Ten
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Create the Dashboard Widget and content of the Popular pages
*
* @since 1.3
*
* @param bool $daily Switch for Daily or Overall popular posts.
* @param int $page Which page of the lists are we on.
* @param int $limit Maximum number of posts per page.
* @param bool $widget Is this a WordPress widget.
* @return Formatted list of popular posts
*/
function tptn_pop_display( $daily = false, $page = 0, $limit = false, $widget = false ) {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
if ( $daily ) {
$table_name .= '_daily'; // If we're viewing daily posts, set this to true.
}
if ( ! $limit ) {
$limit = tptn_get_option( 'limit' );
}
$results = get_tptn_posts(
array(
'is_widget' => 1,
'daily' => $daily,
'limit' => $limit,
'post_types' => 'all',
)
);
$output = '<div id="tptn_popular_posts' . ( $daily ? '_daily' : '' ) . '">';
if ( $results ) {
$output .= '<ul>';
foreach ( $results as $result ) {
$output .= '<li><a href="' . get_permalink( $result->ID ) . '">' . get_the_title( $result->ID ) . '</a>';
$output .= ' (' . tptn_number_format_i18n( $result->visits ) . ')';
$output .= '</li>';
}
$output .= '</ul>';
}
$output .= '<p style="text-align:center">';
if ( $daily ) {
$output .= '<a href="' . admin_url( 'admin.php?page=tptn_popular_posts&orderby=daily_count&order=desc' ) . '">' . __( 'View all daily popular posts', 'top-10' ) . '</a>';
} else {
$output .= '<a href="' . admin_url( 'admin.php?page=tptn_popular_posts&orderby=total_count&order=desc' ) . '">' . __( 'View all popular posts', 'top-10' ) . '</a>';
}
$output .= '</p>';
$output .= '<p style="text-align:center;border-top: #000 1px solid">';
/* translators: 1: Top 10 page link. */
$output .= sprintf( __( 'Popular posts by <a href="%s" target="_blank">Top 10 plugin</a>', 'top-10' ), esc_url( 'https://webberzone.com/plugins/top-10/' ) );
$output .= '</p>';
$output .= '</div>';
/**
* Filters the dashboard widget output
*
* @since 1.3
*
* @param string $output Text output
* @param bool $daily Switch for Daily or Overall popular posts.
* @param int $page Which page of the lists are we on.
* @param int $limit Maximum number of posts per page.
* @param bool $widget Is this a WordPress widget.
*/
return apply_filters( 'tptn_pop_display', $output, $daily, $page, $limit, $widget );
}
/**
* Widget for Popular Posts.
*
* @since 1.1
*/
function tptn_pop_dashboard() {
echo tptn_pop_display( false, 0, 10, true ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Widget for Daily Popular Posts.
*
* @since 1.2
*/
function tptn_pop_daily_dashboard() {
echo tptn_pop_display( true, 0, 10, true ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Function to add the widgets to the Dashboard.
*
* @since 1.1
*/
function tptn_pop_dashboard_setup() {
if ( ( current_user_can( 'manage_options' ) ) || ( tptn_get_option( 'show_count_non_admins' ) ) ) {
wp_add_dashboard_widget(
'tptn_pop_dashboard',
__( 'Popular Posts', 'top-10' ),
'tptn_pop_dashboard'
);
wp_add_dashboard_widget(
'tptn_pop_daily_dashboard',
__( 'Daily Popular Posts', 'top-10' ),
'tptn_pop_daily_dashboard'
);
}
}
add_action( 'wp_dashboard_setup', 'tptn_pop_dashboard_setup' );

View File

@@ -0,0 +1,266 @@
<?php
/**
* Top 10 Meta box functions.
*
* Accessible on Edit Posts, Pages and other custom post type screens
*
* @package Top_Ten
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Function to add meta box in Write screens.
*
* @since 1.9.10
*
* @param text $post_type Post type.
*/
function tptn_add_meta_box( $post_type ) {
// If metaboxes are disabled, then exit.
if ( ! tptn_get_option( 'show_metabox' ) ) {
return;
}
// If current user isn't an admin and we're restricting metaboxes to admins only, then exit.
if ( ! current_user_can( 'manage_options' ) && tptn_get_option( 'show_metabox_admins' ) ) {
return;
}
$args = array(
'public' => true,
);
$post_types = get_post_types( $args );
/**
* Filter post types on which the meta box is displayed
*
* @since 2.2.0
*
* @param array $post_types Array of post types
*/
$post_types = apply_filters( 'tptn_meta_box_post_types', $post_types );
if ( in_array( $post_type, $post_types, true ) ) {
add_meta_box(
'tptn_metabox',
'Top 10',
'tptn_call_meta_box',
$post_type,
'advanced',
'default'
);
}
}
add_action( 'add_meta_boxes', 'tptn_add_meta_box' );
/**
* Function to call the meta box.
*
* @since 1.9.10
*/
function tptn_call_meta_box() {
global $wpdb, $post;
$table_name = $wpdb->base_prefix . 'top_ten';
// Add an nonce field so we can check for it later.
wp_nonce_field( 'tptn_meta_box', 'tptn_meta_box_nonce' );
// Get the number of visits for the post being editted.
$resultscount = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"SELECT postnumber, cntaccess FROM {$table_name} WHERE postnumber = %d AND blog_id = %d ", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$post->ID,
get_current_blog_id()
)
);
$total_count = $resultscount ? $resultscount->cntaccess : 0;
// Get the post meta.
$tptn_post_meta = get_post_meta( $post->ID, 'tptn_post_meta', true );
// Disable display option.
if ( isset( $tptn_post_meta['disable_here'] ) ) {
$disable_here = $tptn_post_meta['disable_here'];
} else {
$disable_here = 0;
}
if ( isset( $tptn_post_meta['exclude_this_post'] ) ) {
$exclude_this_post = $tptn_post_meta['exclude_this_post'];
} else {
$exclude_this_post = 0;
}
?>
<p>
<label for="total_count"><strong><?php esc_html_e( 'Visit count:', 'top-10' ); ?></strong></label>
<input type="text" id="total_count" name="total_count" value="<?php echo esc_attr( $total_count ); ?>" style="width:100%" />
<em><?php esc_html_e( 'Enter a number above to update the visit count. Leaving the above box blank will set the count to zero', 'top-10' ); ?></em>
<input type="hidden" id="total_count_original" name="total_count_original" value="<?php echo esc_attr( $total_count ); ?>">
</p>
<?php
$results = get_post_meta( $post->ID, tptn_get_option( 'thumb_meta' ), true );
$value = ( $results ) ? $results : '';
?>
<p>
<label for="disable_here"><strong><?php esc_html_e( 'Disable Popular Posts display:', 'top-10' ); ?></strong></label>
<input type="checkbox" id="disable_here" name="disable_here" <?php checked( 1, $disable_here, true ); ?> />
<br />
<em><?php esc_html_e( 'If this is checked, then Top 10 will not display the popular posts widgets when viewing this post.', 'top-10' ); ?></em>
</p>
<p>
<label for="exclude_this_post"><strong><?php esc_html_e( 'Exclude this post from the popular posts list:', 'top-10' ); ?></strong></label>
<input type="checkbox" id="exclude_this_post" name="exclude_this_post" <?php checked( 1, $exclude_this_post, true ); ?> />
<br />
<em><?php esc_html_e( 'If this is checked, then this post will be excluded from the popular posts list.', 'top-10' ); ?></em>
</p>
<p>
<label for="thumb_meta"><strong><?php esc_html_e( 'Location of thumbnail:', 'top-10' ); ?></strong></label>
<input type="text" id="thumb_meta" name="thumb_meta" value="<?php echo esc_url( $value ); ?>" style="width:100%" />
<em><?php esc_html_e( "Enter the full URL to the image (JPG, PNG or GIF) you'd like to use. This image will be used for the post. It will be resized to the thumbnail size set under Top 10 Settings &raquo; Thumbnail options.", 'top-10' ); ?></em>
<em><?php esc_html_e( 'The URL above is saved in the meta field:', 'top-10' ); ?></em><strong><?php echo esc_attr( tptn_get_option( 'thumb_meta' ) ); ?></strong>
</p>
<p>
<?php if ( function_exists( 'crp_read_options' ) ) { ?>
<em style="color:red">
<?php
/* translators: 1: Plugin name */
printf( __( 'You have %1$s installed. If you are trying to modify the thumbnail, then you will need to make the same change in the %1$s meta box on this page.', 'top-10' ), 'Contextual Related Posts' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</em>
<?php } ?>
</p>
<?php
if ( $results ) {
echo '<img src="' . esc_url( $value ) . '" style="max-width:100%" />';
}
}
/**
* Function to save the meta box.
*
* @since 1.9.10
*
* @param int $post_id Post ID.
*/
function tptn_save_meta_box( $post_id ) {
global $wpdb;
$tptn_post_meta = array();
$table_name = $wpdb->base_prefix . 'top_ten';
// Bail if we're doing an auto save.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// If our nonce isn't there, or we can't verify it, bail.
if ( ! isset( $_POST['tptn_meta_box_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['tptn_meta_box_nonce'] ), 'tptn_meta_box' ) ) {
return;
}
// If our current user can't edit this post, bail.
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
// Update the posts view count.
if ( isset( $_POST['total_count'] ) && isset( $_POST['total_count_original'] ) ) {
$total_count = intval( $_POST['total_count'] );
$total_count_original = intval( $_POST['total_count_original'] );
$blog_id = get_current_blog_id();
if ( 0 === $total_count ) {
$wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"DELETE FROM {$table_name} WHERE postnumber = %d AND blog_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$post_id,
$blog_id
)
);
} elseif ( $total_count_original !== $total_count ) {
$wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"INSERT INTO {$table_name} (postnumber, cntaccess, blog_id) VALUES( %d, %d, %d ) ON DUPLICATE KEY UPDATE cntaccess= %d ", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$post_id,
$total_count,
$blog_id,
$total_count
)
);
}
}
// Update the thumbnail URL.
if ( isset( $_POST['thumb_meta'] ) ) {
$thumb_meta = empty( $_POST['thumb_meta'] ) ? '' : sanitize_text_field( wp_unslash( $_POST['thumb_meta'] ) );
}
if ( ! empty( $thumb_meta ) ) {
update_post_meta( $post_id, tptn_get_option( 'thumb_meta' ), $thumb_meta );
} else {
delete_post_meta( $post_id, tptn_get_option( 'thumb_meta' ) );
}
// Disable posts.
if ( isset( $_POST['disable_here'] ) ) {
$tptn_post_meta['disable_here'] = 1;
} else {
$tptn_post_meta['disable_here'] = 0;
}
if ( isset( $_POST['exclude_this_post'] ) ) {
$tptn_post_meta['exclude_this_post'] = 1;
} else {
$tptn_post_meta['exclude_this_post'] = 0;
}
/**
* Filter the Top 10 Post meta variable which contains post-specific settings
*
* @since 2.2.0
*
* @param array $tptn_post_meta Top 10 post-specific settings
* @param int $post_id Post ID
*/
$tptn_post_meta = apply_filters( 'tptn_post_meta', $tptn_post_meta, $post_id );
$tptn_post_meta_filtered = array_filter( $tptn_post_meta );
/**** Now we can start saving */
if ( empty( $tptn_post_meta_filtered ) ) { // Checks if all the array items are 0 or empty.
delete_post_meta( $post_id, 'tptn_post_meta' ); // Delete the post meta if no options are set.
} else {
update_post_meta( $post_id, 'tptn_post_meta', $tptn_post_meta );
}
/**
* Action triggered when saving Contextual Related Posts meta box settings
*
* @since 2.2
*
* @param int $post_id Post ID
*/
do_action( 'tptn_save_meta_box', $post_id );
}
add_action( 'save_post', 'tptn_save_meta_box' );
add_action( 'edit_attachment', 'tptn_save_meta_box' );

View File

@@ -0,0 +1,289 @@
<?php
/**
* The admin-specific functionality of the plugin.
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Creates the admin submenu pages under the Downloads menu and assigns their
* links to global variables
*
* @since 2.5.0
*
* @global string $tptn_settings_page Settings page hook.
* @global string $tptn_settings_popular_posts Popular posts page hook.
* @global string $tptn_settings_popular_posts_daily Daily popular page hook.
* @global string $tptn_settings_tools_help Tools page hook.
* @global string $tptn_settings_exim_help Export/Import page hook.
* @return void
*/
function tptn_add_admin_pages_links() {
global $tptn_settings_page, $tptn_settings_tools_help, $tptn_settings_popular_posts, $tptn_settings_popular_posts_daily, $tptn_settings_exim_help;
$tptn_settings_page = add_submenu_page( 'tptn_dashboard', esc_html__( 'Top 10 Settings', 'top-10' ), esc_html__( 'Settings', 'top-10' ), 'manage_options', 'tptn_options_page', 'tptn_options_page' );
add_action( "load-$tptn_settings_page", 'tptn_settings_help' );
// Initialise Top 10 Statistics pages.
$tptn_stats_screen = new Top_Ten_Statistics();
$tptn_settings_popular_posts = add_submenu_page( 'tptn_dashboard', __( 'Top 10 Popular Posts', 'top-10' ), __( 'Popular Posts', 'top-10' ), 'manage_options', 'tptn_popular_posts', array( $tptn_stats_screen, 'plugin_settings_page' ) );
add_action( "load-$tptn_settings_popular_posts", array( $tptn_stats_screen, 'screen_option' ) );
$tptn_settings_popular_posts_daily = add_submenu_page( 'tptn_dashboard', __( 'Top 10 Daily Popular Posts', 'top-10' ), __( 'Daily Popular Posts', 'top-10' ), 'manage_options', 'tptn_popular_posts&orderby=daily_count&order=desc', array( $tptn_stats_screen, 'plugin_settings_page' ) );
add_action( "load-$tptn_settings_popular_posts_daily", array( $tptn_stats_screen, 'screen_option' ) );
// Add links to Tools pages.
$tptn_settings_tools_help = add_submenu_page( 'tptn_dashboard', esc_html__( 'Top 10 Tools', 'top-10' ), esc_html__( 'Tools', 'top-10' ), 'manage_options', 'tptn_tools_page', 'tptn_tools_page' );
add_action( "load-$tptn_settings_tools_help", 'tptn_settings_tools_help' );
$tptn_settings_exim_help = add_submenu_page( 'tptn_dashboard', esc_html__( 'Top 10 Import Export Tables', 'top-10' ), esc_html__( 'Import/Export', 'top-10' ), 'manage_options', 'tptn_exim_page', 'tptn_exim_page' );
add_action( "load-$tptn_settings_exim_help", 'tptn_settings_exim_help' );
}
add_action( 'admin_menu', 'tptn_add_admin_pages_links', 11 );
/**
* Customise the taxonomy columns.
*
* @since 2.5.0
* @param array $columns Columns in the admin view.
* @return array Updated columns.
*/
function tptn_tax_columns( $columns ) {
// Remove the description column.
unset( $columns['description'] );
$new_columns = array(
'tax_id' => 'ID',
);
return array_merge( $columns, $new_columns );
}
add_filter( 'manage_edit-tptn_category_columns', 'tptn_tax_columns' );
add_filter( 'manage_edit-tptn_category_sortable_columns', 'tptn_tax_columns' );
add_filter( 'manage_edit-tptn_tag_columns', 'tptn_tax_columns' );
add_filter( 'manage_edit-tptn_tag_sortable_columns', 'tptn_tax_columns' );
/**
* Add taxonomy ID to the admin column.
*
* @since 2.5.0
*
* @param string $value Deprecated.
* @param string $name Name of the column.
* @param int|string $id Category ID.
* @return int|string
*/
function tptn_tax_id( $value, $name, $id ) {
return 'tax_id' === $name ? $id : $value;
}
add_filter( 'manage_tptn_category_custom_column', 'tptn_tax_id', 10, 3 );
add_filter( 'manage_tptn_tag_custom_column', 'tptn_tax_id', 10, 3 );
/**
* Add rating links to the admin dashboard
*
* @since 2.5.0
*
* @param string $footer_text The existing footer text.
* @return string Updated Footer text
*/
function tptn_admin_footer( $footer_text ) {
if ( get_current_screen()->parent_base === 'tptn_dashboard' ) {
$text = sprintf(
/* translators: 1: Top 10 website, 2: Plugin reviews link. */
__( 'Thank you for using <a href="%1$s" target="_blank">Top 10</a>! Please <a href="%2$s" target="_blank">rate us</a> on <a href="%2$s" target="_blank">WordPress.org</a>', 'top-10' ),
'https://webberzone.com/top-10',
'https://wordpress.org/support/plugin/top-10/reviews/#new-post'
);
return str_replace( '</span>', '', $footer_text ) . ' | ' . $text . '</span>';
} else {
return $footer_text;
}
}
add_filter( 'admin_footer_text', 'tptn_admin_footer' );
/**
* Add CSS to Admin head
*
* @since 2.5.0
*
* return void
*/
function tptn_admin_head() {
?>
<style type="text/css" media="screen">
#dashboard_right_now .tptn-article-count:before {
content: "\f331";
}
</style>
<?php
}
add_filter( 'admin_head', 'tptn_admin_head' );
/**
* Adding WordPress plugin action links.
*
* @version 1.9.2
*
* @param array $links Action links.
* @return array Links array with our settings link added.
*/
function tptn_plugin_actions_links( $links ) {
return array_merge(
array(
'settings' => '<a href="' . admin_url( 'admin.php?page=tptn_dashboard' ) . '">' . __( 'Settings', 'top-10' ) . '</a>',
),
$links
);
}
add_filter( 'plugin_action_links_' . plugin_basename( TOP_TEN_PLUGIN_FILE ), 'tptn_plugin_actions_links' );
/**
* Add links to the plugin action row.
*
* @since 1.5
*
* @param array $links Action links.
* @param array $file Plugin file name.
* @return array Links array with our links added
*/
function tptn_plugin_actions( $links, $file ) {
$plugin = plugin_basename( TOP_TEN_PLUGIN_FILE );
if ( $file === $plugin ) {
$links[] = '<a href="https://wordpress.org/support/plugin/top-10/">' . __( 'Support', 'top-10' ) . '</a>';
$links[] = '<a href="https://ajaydsouza.com/donate/">' . __( 'Donate', 'top-10' ) . '</a>';
$links[] = '<a href="https://github.com/WebberZone/top-10">' . __( 'Contribute', 'top-10' ) . '</a>';
}
return $links;
}
add_filter( 'plugin_row_meta', 'tptn_plugin_actions', 10, 2 );
/**
* Add a menu entry to the Network Admin
*
* @since 2.8.0
*/
function tptn_network_admin_menu_links() {
global $tptn_network_pop_posts_page;
// Initialise Top 10 Statistics pages.
$tptn_stats_screen = new Top_Ten_Network_Statistics();
$tptn_network_pop_posts_page = add_menu_page( esc_html__( 'Top 10 - Network Popular Posts', 'top-10' ), esc_html__( 'Top 10', 'top-10' ), 'manage_network_options', 'tptn_network_pop_posts_page', array( $tptn_stats_screen, 'plugin_settings_page' ), 'dashicons-editor-ol' );
add_action( "load-$tptn_network_pop_posts_page", array( $tptn_stats_screen, 'screen_option' ) );
}
add_action( 'network_admin_menu', 'tptn_network_admin_menu_links' );
/**
* Enqueue Admin JS
*
* @since 2.9.0
*
* @param string $hook The current admin page.
*/
function tptn_load_admin_scripts( $hook ) {
global $tptn_settings_page, $tptn_settings_tools_help, $tptn_settings_popular_posts, $tptn_settings_popular_posts_daily, $tptn_settings_exim_help, $tptn_network_pop_posts_page;
wp_register_script( 'top-ten-admin-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/admin-scripts.min.js', array( 'jquery', 'jquery-ui-tabs', 'jquery-ui-datepicker' ), '1.0', true );
wp_register_script( 'top-ten-suggest-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/top-10-suggest.min.js', array( 'jquery', 'jquery-ui-autocomplete' ), '1.0', true );
wp_register_style(
'tptn-admin-customizer-css',
TOP_TEN_PLUGIN_URL . 'includes/admin/css/top-10-customizer.min.css',
false,
'1.0',
false
);
if ( in_array( $hook, array( $tptn_settings_page, $tptn_settings_tools_help, $tptn_settings_popular_posts, $tptn_settings_popular_posts_daily, $tptn_settings_exim_help, $tptn_network_pop_posts_page . '-network' ), true ) ) {
wp_enqueue_script( 'top-ten-admin-js' );
wp_enqueue_script( 'top-ten-suggest-js' );
wp_enqueue_script( 'plugin-install' );
add_thickbox();
wp_enqueue_code_editor(
array(
'type' => 'text/html',
'codemirror' => array(
'indentUnit' => 2,
'tabSize' => 2,
),
)
);
}
// Only enqueue the styles if this is a popular posts page.
if ( in_array( $hook, array( $tptn_settings_popular_posts, $tptn_settings_popular_posts_daily, $tptn_network_pop_posts_page . '-network' ), true ) ) {
wp_enqueue_style(
'tptn-admin-ui-css',
TOP_TEN_PLUGIN_URL . 'includes/admin/css/top-10-admin.min.css',
false,
'1.0',
false
);
}
}
add_action( 'admin_enqueue_scripts', 'tptn_load_admin_scripts' );
/**
* This function enqueues scripts and styles in the Customizer.
*
* @since 2.9.0
*/
function tptn_customize_controls_enqueue_scripts() {
wp_enqueue_script( 'customize-controls' );
wp_enqueue_script( 'top-ten-suggest-js' );
wp_enqueue_style( 'tptn-admin-customizer-css' );
}
add_action( 'customize_controls_enqueue_scripts', 'tptn_customize_controls_enqueue_scripts', 99 );
/**
* This function enqueues scripts and styles on widgets.php.
*
* @since 2.9.0
*
* @param string $hook The current admin page.
*/
function tptn_enqueue_scripts_widgets( $hook ) {
if ( 'widgets.php' !== $hook ) {
return;
}
wp_enqueue_script( 'top-ten-suggest-js' );
wp_enqueue_style( 'tptn-admin-customizer-css' );
}
add_action( 'admin_enqueue_scripts', 'tptn_enqueue_scripts_widgets', 99 );

View File

@@ -0,0 +1,118 @@
<?php
/**
* Top 10 Cache interface.
*
* @package Top_Ten
*/
/**
* Function to clear the Top 10 Cache with Ajax.
*
* @since 2.2.0
*/
function tptn_ajax_clearcache() {
$count = tptn_cache_delete();
exit(
wp_json_encode(
array(
'success' => 1,
/* translators: 1: Number of entries. */
'message' => sprintf( _n( '%s entry cleared', '%s entries cleared', $count, 'text-domain' ), number_format_i18n( $count ) ),
)
)
);
}
add_action( 'wp_ajax_tptn_clear_cache', 'tptn_ajax_clearcache' );
/**
* Get the default meta keys used for the cache
*
* @return array Transient meta keys
*/
function tptn_cache_get_keys() {
$meta_keys = array(
'tptn_total',
'tptn_daily',
'tptn_total_shortcode',
'tptn_daily_shortcode',
'tptn_total_widget',
'tptn_daily_widget',
'tptn_total_manual',
'tptn_daily_manual',
);
$meta_keys = array_merge( $meta_keys, tptn_cache_get_widget_keys() );
/**
* Filters the array containing the various cache keys.
*
* @since 1.9
*
* @param array $default_meta_keys Array of meta keys
*/
return apply_filters( 'tptn_cache_keys', $meta_keys );
}
/**
* Delete the Top 10 cache.
*
* @since 2.3.0
*
* @param array $transients Array of transients to delete.
* @return int Number of transients deleted.
*/
function tptn_cache_delete( $transients = array() ) {
$loop = 0;
$default_transients = tptn_cache_get_keys();
if ( ! empty( $transients ) ) {
$transients = array_intersect( $default_transients, (array) $transients );
} else {
$transients = $default_transients;
}
foreach ( $transients as $transient ) {
$del = delete_transient( $transient );
if ( $del ) {
$loop++;
}
}
return $loop;
}
/**
* Get the transient names for the Top 10 widgets.
*
* @since 2.3.0
*
* @return array Top 10 Cache widget keys.
*/
function tptn_cache_get_widget_keys() {
global $wpdb;
$keys = array();
$sql = "
SELECT option_name
FROM {$wpdb->options}
WHERE `option_name` LIKE '_transient_tptn_%'
";
$results = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
if ( is_array( $results ) ) {
foreach ( $results as $result ) {
$keys[] = str_replace( '_transient_', '', $result->option_name );
}
}
return apply_filters( 'tptn_cache_get_widget_keys', $keys );
}

View File

@@ -0,0 +1,529 @@
<?php
/**
* Dashboard.
*
* @link https://webberzone.com
* @since 3.0.0
*
* @package Top 10
* @subpackage Admin/Dashboard
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Top_Ten_Dashboard class.
*
* @since 3.0.0
*/
class Top_Ten_Dashboard {
/**
* Class instance.
*
* @since 3.0.0
*
* @var class Class instance.
*/
public static $instance;
/**
* Parent Menu ID.
*
* @since 3.0.0
*
* @var string Parent Menu ID.
*/
public $parent_id;
/**
* Singleton instance.
*
* @since 3.0.0
*/
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor class.
*
* @since 3.0.0
*/
public function __construct() {
add_action( 'admin_menu', array( $this, 'admin_menu' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'wp_ajax_tptn_chart_data', array( $this, 'get_chart_data' ) );
}
/**
* Render the settings page.
*
* @since 3.0.0
*/
public function plugin_settings_page() {
ob_start();
// Add date selector.
$chart_to_date = current_time( 'd M Y' );
$chart_from_date = gmdate( 'd M Y', strtotime( '-1 week' ) );
$post_date_from = ( isset( $_REQUEST['post-date-filter-from'] ) && check_admin_referer( 'tptn-dashboard' ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-from'] ) ) : $chart_from_date;
$post_date_to = ( isset( $_REQUEST['post-date-filter-to'] ) && check_admin_referer( 'tptn-dashboard' ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-to'] ) ) : $chart_to_date;
?>
<div class="wrap">
<h1><?php esc_html_e( 'Top 10 Dashboard', 'top-10' ); ?></h1>
<?php settings_errors(); ?>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<form method="post" >
<?php wp_nonce_field( 'tptn-dashboard' ); ?>
<div>
<input type="text" id="datepicker-from" name="post-date-filter-from" value="<?php echo esc_attr( $post_date_from ); ?>" size="11" />
<input type="text" id="datepicker-to" name="post-date-filter-to" value="<?php echo esc_attr( $post_date_to ); ?>" size="11" />
<?php
submit_button(
__( 'Update', 'top-10' ),
'primary',
'filter_action',
false,
array(
'id' => 'top-10-chart-submit',
'onclick' => 'updateChart(); return false;',
)
);
?>
</div>
<div>
<canvas id="visits" width="400" height="150" aria-label="<?php esc_html_e( 'Top 10 Visits', 'top-10' ); ?>" role="img"></canvas>
</div>
</form>
<h2><?php esc_html_e( 'Historical visits', 'top-10' ); ?></h2>
<ul class="nav-tab-wrapper" style="padding:0; border-bottom: 1px solid #ccc;">
<?php
foreach ( $this->get_tabs() as $tab_id => $tab_name ) {
echo '<li style="padding:0; border:0; margin:0;"><a href="#' . esc_attr( $tab_id ) . '" title="' . esc_attr( $tab_name['title'] ) . '" class="nav-tab">';
echo esc_html( $tab_name['title'] );
echo '</a></li>';
}
?>
</ul>
<form method="post" action="options.php">
<?php foreach ( $this->get_tabs() as $tab_id => $tab_name ) : ?>
<div id="<?php echo esc_attr( $tab_id ); ?>">
<table class="form-table">
<?php
$output = $this->display_popular_posts( $tab_name );
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</table>
<div style="font-weight:bold;padding:5px;">
<?php
$query_args = array(
'order' => 'desc',
);
$daily = ( isset( $tab_name['daily'] ) ) ? $tab_name['daily'] : true;
if ( $daily ) {
$query_args['orderby'] = 'daily_count';
if ( ! empty( $tab_name['from_date'] ) ) {
$query_args['post-date-filter-from'] = gmdate( 'd+M+Y', strtotime( $tab_name['from_date'] ) );
}
if ( ! empty( $tab_name['to_date'] ) ) {
$query_args['post-date-filter-to'] = gmdate( 'd+M+Y', strtotime( $tab_name['to_date'] ) );
}
} else {
$query_args['orderby'] = 'total_count';
}
$url = add_query_arg( $query_args, admin_url( 'admin.php?page=tptn_popular_posts' ) );
?>
<a href="<?php echo esc_url( $url ); ?>"><?php esc_html_e( 'View all popular posts', 'top-10' ); ?> &raquo;</a>
</div>
</div><!-- /#tab_id-->
<?php endforeach; ?>
</form>
</div><!-- /#post-body-content -->
<div id="postbox-container-1" class="postbox-container">
<div id="side-sortables" class="meta-box-sortables ui-sortable">
<?php include_once 'sidebar.php'; ?>
</div><!-- /#side-sortables -->
</div><!-- /#postbox-container-1 -->
</div><!-- /#post-body -->
<br class="clear" />
</div><!-- /#poststuff -->
</div><!-- /.wrap -->
<?php
echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Admin Menu.
*
* @since 3.0.0
*/
public function admin_menu() {
$this->parent_id = add_menu_page( esc_html__( 'Top 10 Dashboard', 'top-10' ), esc_html__( 'Top 10', 'top-10' ), 'manage_options', 'tptn_dashboard', array( $this, 'plugin_settings_page' ), 'dashicons-editor-ol' );
add_submenu_page( 'tptn_dashboard', esc_html__( 'Top 10 Dashboard', 'top-10' ), esc_html__( 'Dashboard', 'top-10' ), 'manage_options', 'tptn_dashboard', array( $this, 'plugin_settings_page' ) );
add_action( 'load-' . $this->parent_id, array( $this, 'help_tabs' ) );
}
/**
* Enqueue scripts in admin area.
*
* @since 3.0.0
*
* @param string $hook The current admin page.
*/
public function admin_enqueue_scripts( $hook ) {
wp_register_script( 'top-ten-moment-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/moment.min.js', array(), '1.0', true );
wp_register_script( 'top-ten-chart-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/chart.min.js', array(), '1.0', true );
wp_register_script( 'top-ten-chart-datalabels-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/chartjs-plugin-datalabels.min.js', array( 'top-ten-chart-js' ), '1.0', true );
wp_register_script( 'top-ten-chartjs-adapter-moment-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/chartjs-adapter-moment.min.js', array( 'top-ten-moment-js', 'top-ten-chart-js' ), '1.0', true );
wp_register_script( 'top-ten-chart-data-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/chart-data.min.js', array( 'jquery', 'top-ten-chart-js', 'top-ten-chart-datalabels-js', 'top-ten-moment-js', 'top-ten-chartjs-adapter-moment-js' ), '1.0', true );
wp_register_script( 'top-ten-admin-js', TOP_TEN_PLUGIN_URL . 'includes/admin/js/admin-scripts.min.js', array( 'jquery', 'jquery-ui-tabs', 'jquery-ui-datepicker' ), '1.0', true );
if ( $hook === $this->parent_id ) {
wp_enqueue_script( 'top-ten-chart-js' );
wp_enqueue_script( 'top-ten-chart-datalabels-js' );
wp_enqueue_script( 'top-ten-moment-js' );
wp_enqueue_script( 'top-ten-chartjs-adapter-moment-js' );
wp_enqueue_script( 'top-ten-chart-data-js' );
wp_enqueue_script( 'top-ten-admin-js' );
wp_enqueue_style(
'tptn-admin-ui-css',
TOP_TEN_PLUGIN_URL . 'includes/admin/css/top-10-admin.min.css',
false,
'1.0',
false
);
wp_localize_script(
'top-ten-chart-data-js',
'tptn_chart_data',
array(
'security' => wp_create_nonce( 'tptn-dashboard' ),
'datasetlabel' => __( 'Visits', 'top-10' ),
'charttitle' => __( 'Daily Visits', 'top-10' ),
)
);
}
}
/**
* Function to add an action to search for tags using Ajax.
*
* @since 3.0.0
*/
public function get_chart_data() {
global $wpdb;
check_ajax_referer( 'tptn-dashboard', 'security' );
$blog_id = get_current_blog_id();
// Add date selector.
$to_date = isset( $_REQUEST['to_date'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['to_date'] ) ) : current_time( 'd M Y' );
$from_date = isset( $_REQUEST['from_date'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['from_date'] ) ) : gmdate( 'd M Y', strtotime( '-1 week' ) );
$post_date_from = gmdate( 'Y-m-d', strtotime( $from_date ) );
$post_date_to = gmdate( 'Y-m-d', strtotime( $to_date ) );
$sql = $wpdb->prepare(
" SELECT SUM(cntaccess) AS visits, DATE(dp_date) as date
FROM {$wpdb->base_prefix}top_ten_daily
WHERE DATE(dp_date) >= DATE(%s)
AND DATE(dp_date) <= DATE(%s)
AND blog_id = %d
GROUP BY date
ORDER BY date ASC
",
$post_date_from,
$post_date_to,
$blog_id
);
$result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$data = array();
foreach ( $result as $row ) {
$data[] = $row;
}
echo wp_json_encode( $data );
wp_die();
}
/**
* Array containing the settings' sections.
*
* @since 3.0.0
*
* @return array Settings array
*/
public function get_tabs() {
$tabs = array(
'today' => array(
'title' => __( 'Today', 'top-10' ),
'from_date' => current_time( 'd M Y' ),
'to_date' => current_time( 'd M Y' ),
),
'yesterday' => array(
'title' => __( 'Yesterday', 'top-10' ),
'from_date' => gmdate( 'd M Y', strtotime( '-1 day' ) ),
'to_date' => gmdate( 'd M Y', strtotime( '-1 day' ) ),
),
'lastweek' => array(
'title' => __( 'Last 7 days', 'top-10' ),
'from_date' => gmdate( 'd M Y', strtotime( '-1 week' ) ),
'to_date' => current_time( 'd M Y' ),
),
'lastmonth' => array(
'title' => __( 'Last 30 days', 'top-10' ),
'from_date' => gmdate( 'd M Y', strtotime( '-30 days' ) ),
'to_date' => current_time( 'd M Y' ),
),
'overall' => array(
'title' => __( 'All time', 'top-10' ),
'daily' => false,
),
);
return $tabs;
}
/**
* Get popular posts for a date range.
*
* @since 3.0.0
*
* @param string|array $args {
* Optional. Array or string of Query parameters.
*
* @type bool $daily Set to true to get the daily/custom period posts. False for overall.
* @type string $from_date From date. A date/time string.
* @type int $numberposts Number of posts to fetch.
* @type string $to_date To date. A date/time string.
* }
* @return string HTML table with popular posts.
*/
public function display_popular_posts( $args = array() ) {
$output = '';
$defaults = array(
'daily' => true,
'from_date' => null,
'numberposts' => 20,
'to_date' => null,
);
$args = wp_parse_args( $args, $defaults );
$results = $this->get_popular_posts( $args );
ob_start();
if ( $results ) :
?>
<table class="widefat striped">
<?php
foreach ( $results as $result ) :
$visits = tptn_number_format_i18n( $result->visits );
$result = get_post( $result->ID );
?>
<tr>
<td><a href="<?php echo esc_url( get_permalink( $result ) ); ?>" target="_blank"><?php echo esc_html( get_the_title( $result ) ); ?></td>
<td><?php echo esc_html( $visits ); ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php else : ?>
<?php esc_html_e( 'Sorry, no popular posts found.', 'top-10' ); ?>
<?php endif; ?>
<?php
$output = ob_get_clean();
return $output;
}
/**
* Retrieve the popular posts.
*
* @since 3.0.0
*
* @param string|array $args {
* Optional. Array or string of Query parameters.
*
* @type array|string $blog_id An array or comma-separated string of blog IDs.
* @type bool $daily Set to true to get the daily/custom period posts. False for overall.
* @type string $from_date From date. A date/time string.
* @type int $numberposts Number of posts to fetch.
* @type int $offset Offset.
* @type string $to_date To date. A date/time string.
* }
* @return array Array of post objects.
*/
public function get_popular_posts( $args = array() ) {
global $wpdb;
// Initialise some variables.
$fields = array();
$where = '';
$join = '';
$groupby = '';
$orderby = '';
$limits = '';
$defaults = array(
'blog_id' => get_current_blog_id(),
'daily' => true,
'from_date' => null,
'numberposts' => 20,
'offset' => 0,
'to_date' => null,
);
$args = wp_parse_args( $args, $defaults );
if ( $args['daily'] ) {
$table_name = $wpdb->base_prefix . 'top_ten_daily';
} else {
$table_name = $wpdb->base_prefix . 'top_ten';
}
// Fields to return.
$fields[] = ( $args['daily'] ) ? "SUM({$table_name}.cntaccess) as visits" : "{$table_name}.cntaccess as visits";
$fields[] = "{$wpdb->posts}.ID";
$fields = implode( ', ', $fields );
// Create the JOIN clause.
$join = " INNER JOIN {$wpdb->posts} ON {$table_name}.postnumber={$wpdb->posts}.ID ";
// Create the base WHERE clause.
$where = $wpdb->prepare( " AND {$table_name}.blog_id = %d ", $args['blog_id'] ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$where .= " AND ($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_status = 'inherit') "; // Show published posts and attachments.
$where .= " AND ($wpdb->posts.post_type <> 'revision' ) "; // No revisions.
if ( isset( $args['from_date'] ) ) {
$from_date = gmdate( 'Y-m-d', strtotime( $args['from_date'] ) );
$where .= $wpdb->prepare( " AND DATE({$table_name}.dp_date) >= DATE(%s) ", $from_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
if ( isset( $args['to_date'] ) ) {
$to_date = gmdate( 'Y-m-d', strtotime( $args['to_date'] ) );
$where .= $wpdb->prepare( " AND DATE({$table_name}.dp_date) <= DATE(%s) ", $to_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
// Create the base GROUP BY clause.
if ( $args['daily'] ) {
$groupby = " {$wpdb->posts}.ID";
}
// Create the base ORDER BY clause.
$orderby = ' visits DESC ';
// Create the base LIMITS clause.
$limits = $wpdb->prepare( ' LIMIT %d, %d ', $args['offset'], $args['numberposts'] );
if ( ! empty( $groupby ) ) {
$groupby = " GROUP BY {$groupby} ";
}
if ( ! empty( $orderby ) ) {
$orderby = " ORDER BY {$orderby} ";
}
$sql = "SELECT DISTINCT $fields FROM {$table_name} $join WHERE 1=1 $where $groupby $orderby $limits";
$result = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
return $result;
}
/**
* Generates the help tabs.
*
* @since 3.0.0
*/
public function help_tabs() {
$screen = get_current_screen();
$screen->set_help_sidebar(
/* translators: 1: Support link. */
'<p>' . sprintf( __( 'For more information or how to get support visit the <a href="%1$s">WebberZone support site</a>.', 'top-10' ), esc_url( 'https://webberzone.com/support/' ) ) . '</p>' .
/* translators: 1: Forum link. */
'<p>' . sprintf( __( 'Support queries should be posted in the <a href="%1$s">WordPress.org support forums</a>.', 'top-10' ), esc_url( 'https://wordpress.org/support/plugin/top-10' ) ) . '</p>' .
'<p>' . sprintf(
/* translators: 1: Github Issues link, 2: Github page. */
__( '<a href="%1$s">Post an issue</a> on <a href="%2$s">GitHub</a> (bug reports only).', 'top-10' ),
esc_url( 'https://github.com/WebberZone/top-10/issues' ),
esc_url( 'https://github.com/WebberZone/top-10' )
) . '</p>'
);
$screen->add_help_tab(
array(
'id' => 'tptn-dashboard-general',
'title' => __( 'General', 'top-10' ),
'content' =>
'<p>' . __( 'This screen displays the historical traffic on your site.', 'top-10' ) . '</p>' .
/* translators: 1: Constant holding number of days data is stored. */
'<p>' . sprintf( __( 'The data is pulled from the daily tables in the database. If you have enabled maintenance then the amount of historical data that is available will be limited to %d days.', 'top-10' ), TOP_TEN_STORE_DATA ) . '</p>' .
'<p>' . __( 'You can change this by setting the constant TOP_TEN_STORE_DATA to the number of days of your choice in your wp-config.php.', 'top-10' ) . '</p>',
)
);
}
}
/**
* Function to initialise stats page.
*
* @since 3.0.0
*/
function tptn_load_dashboard() {
Top_Ten_Dashboard::get_instance();
}
add_action( 'plugins_loaded', 'tptn_load_dashboard' );

View File

@@ -0,0 +1,428 @@
<?php
/**
* Top 10 Display Network statistics table.
*
* @package Top_Ten
* @subpackage Top_Ten_Network_Statistics_Table
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
/**
* Top_Ten_Network_Table class.
*
* @extends WP_List_Table
*/
class Top_Ten_Network_Statistics_Table extends WP_List_Table {
/**
* Class constructor.
*/
public function __construct() {
parent::__construct(
array(
'singular' => __( 'popular_post', 'top-10' ), // Singular name of the listed records.
'plural' => __( 'popular_posts', 'top-10' ), // plural name of the listed records.
)
);
}
/**
* Retrieve the Top 10 posts
*
* @param int $per_page Posts per page.
* @param int $page_number Page number.
* @param array $args Array of arguments.
*
* @return array Array of popular posts
*/
public static function get_popular_posts( $per_page = 20, $page_number = 1, $args = null ) {
global $wpdb;
// Initialise some variables.
$fields = array();
$where = '';
$join = '';
$groupby = '';
$orderby = '';
$limits = '';
$sql = '';
$from_date = isset( $args['post-date-filter-from'] ) ? $args['post-date-filter-from'] : current_time( 'd M Y' );
$from_date = gmdate( 'Y-m-d', strtotime( $from_date ) );
$to_date = isset( $args['post-date-filter-to'] ) ? $args['post-date-filter-to'] : current_time( 'd M Y' );
$to_date = gmdate( 'Y-m-d', strtotime( $to_date ) );
/* Start creating the SQL */
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily AS ttd';
$table_name = $wpdb->base_prefix . 'top_ten AS ttt';
// Fields to return.
$fields[] = 'ttt.postnumber as ID';
$fields[] = 'ttt.cntaccess as total_count';
$fields[] = 'SUM(ttd.cntaccess) as daily_count';
$fields[] = 'ttt.blog_id as blog_id';
$fields = implode( ', ', $fields );
// Create the JOIN clause.
$join = $wpdb->prepare(
" LEFT JOIN (
SELECT * FROM {$table_name_daily} " . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
'WHERE DATE(ttd.dp_date) >= DATE(%s) AND DATE(ttd.dp_date) <= DATE(%s)
) AS ttd
ON ttt.postnumber=ttd.postnumber
',
$from_date,
$to_date
);
// Create the base GROUP BY clause.
$groupby = ' ID, blog_id ';
// Create the base ORDER BY clause.
$orderby = ' total_count DESC ';
if ( ! empty( $_REQUEST['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$orderby = sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $orderby, array( 'daily_count', 'total_count' ) ) ) { //phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
$orderby = ' total_count ';
}
if ( ! empty( $_REQUEST['order'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$order = sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( in_array( $order, array( 'asc', 'ASC', 'desc', 'DESC' ) ) ) { //phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
$orderby .= ' ' . $order;
} else {
$orderby .= ' DESC';
}
}
}
// Create the base LIMITS clause.
$limits = $wpdb->prepare( ' LIMIT %d, %d ', ( $page_number - 1 ) * $per_page, $per_page );
if ( ! empty( $groupby ) ) {
$groupby = " GROUP BY {$groupby} ";
}
if ( ! empty( $orderby ) ) {
$orderby = " ORDER BY {$orderby} ";
}
$sql = "SELECT $fields FROM {$table_name} $join WHERE 1=1 $where $groupby $orderby $limits";
$result = $wpdb->get_results( $sql, 'ARRAY_A' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
return $result;
}
/**
* Delete the post count for this post.
*
* @param int $id post ID.
*/
public static function delete_post_count( $id ) {
global $wpdb;
$wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
"{$wpdb->base_prefix}top_ten",
array(
'postnumber' => $id,
),
array( '%d' )
);
$wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
"{$wpdb->base_prefix}top_ten_daily",
array(
'postnumber' => $id,
),
array( '%d' )
);
}
/**
* Returns the count of records in the database.
*
* @param string $args Array of arguments.
* @return null|string null|string
*/
public static function record_count( $args = null ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
global $wpdb;
$sql = $wpdb->prepare(
"
SELECT COUNT(*) FROM {$wpdb->base_prefix}top_ten as ttt
INNER JOIN {$wpdb->posts} ON ttt.postnumber=ID
WHERE blog_id=%d
AND ($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_status = 'inherit')
",
get_current_blog_id()
);
return $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Text displayed when no post data is available
*/
public function no_items() {
esc_html_e( 'No popular posts available.', 'top-10' );
}
/**
* Render a column when no column specific method exist.
*
* @param array $item Current item.
* @param string $column_name Column name.
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'total_count':
case 'daily_count':
return tptn_number_format_i18n( absint( $item[ $column_name ] ) );
default:
// Show the whole array for troubleshooting purposes.
return print_r( $item, true ); //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
}
/**
* Render the checkbox column.
*
* @param array $item Current item.
* @return string
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
'bulk-delete',
$item['ID']
);
}
/**
* Render the title column.
*
* @param array $item Current item.
* @return string
*/
public function column_title( $item ) {
$blog_post = get_blog_post( $item['blog_id'], $item['ID'] );
if ( null === $blog_post ) {
return __( 'Invalid post ID. This post might have been deleted.', 'top-10' );
} else {
// Return the title contents.
return sprintf(
'<a href="%3$s" target="_blank">%1$s</a> <span style="color:silver">(id:%2$s)</span>',
$blog_post->post_title,
$item['ID'],
get_blog_permalink( $item['blog_id'], $item['ID'] )
);
}
}
/**
* Handles the post date column output.
*
* @param array $item Current item.
* @return void
*/
public function column_date( $item ) {
$blog_post = get_blog_post( $item['blog_id'], $item['ID'] );
if ( $blog_post ) {
$m_time = $blog_post->post_date;
$h_time = mysql2date( __( 'Y/m/d' ), $m_time );
echo '<abbr title="' . esc_attr( $h_time ) . '">' . esc_attr( $h_time ) . '</abbr>';
}
}
/**
* Handles the blog id column output.
*
* @param array $item Current item.
* @return void
*/
public function column_blog_id( $item ) {
$blog_details = get_blog_details( $item['blog_id'] );
printf(
'<a href="%s" target="_blank">%s</a>',
esc_url(
add_query_arg(
array(
'page' => 'tptn_popular_posts',
),
get_admin_url( $item['blog_id'] ) . 'admin.php'
)
),
esc_html( $blog_details->blogname )
);
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'title' => __( 'Title', 'top-10' ),
'blog_id' => __( 'Blog', 'top-10' ),
'date' => __( 'Date', 'top-10' ),
'total_count' => __( 'Total visits', 'top-10' ),
'daily_count' => __( 'Daily visits', 'top-10' ),
);
/**
* Filter the columns displayed in the Posts list table.
*
* @since 1.5.0
*
* @param array $columns An array of column names.
*/
return apply_filters( 'manage_pop_posts_columns', $columns );
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'total_count' => array( 'total_count', false ),
'daily_count' => array( 'daily_count', false ),
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
$actions = array(
'bulk-delete' => __( 'Delete Count', 'top-10' ),
);
return $actions;
}
/**
* Handles data query and filter, sorting, and pagination.
*
* @param array $args Array of arguments.
*/
public function prepare_items( $args = null ) {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
$per_page = $this->get_items_per_page( 'pop_posts_per_page', 20 );
$current_page = $this->get_pagenum();
$total_items = self::record_count( $args );
$this->set_pagination_args(
array(
'total_items' => $total_items, // WE have to calculate the total number of items.
'per_page' => $per_page, // WE have to determine how many items to show on a page.
'total_pages' => ceil( $total_items / $per_page ), // WE have to calculate the total number of pages.
)
);
$this->items = self::get_popular_posts( $per_page, $current_page, $args );
}
/**
* Handles any bulk actions
*/
public function process_bulk_action() {
// Detect when a bulk action is being triggered...
if ( 'delete' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$postid = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'tptn_delete_entry' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
self::delete_post_count( $postid );
} else {
die( esc_html__( 'Are you sure you want to do this', 'top-10' ) );
}
}
// If the delete bulk action is triggered.
if ( ( isset( $_REQUEST['action'] ) && 'bulk-delete' === $_REQUEST['action'] )
|| ( isset( $_REQUEST['action2'] ) && 'bulk-delete' === $_REQUEST['action2'] )
) {
$delete_ids = isset( $_REQUEST['bulk-delete'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['bulk-delete'] ) ) : array();
// Loop over the array of record IDs and delete them.
foreach ( $delete_ids as $id ) {
self::delete_post_count( $id );
}
}
}
/**
* Adds extra navigation elements to the table.
*
* @param string $which Which part of the table are we.
*/
public function extra_tablenav( $which ) {
?>
<div class="alignleft actions">
<?php
if ( 'top' === $which ) {
ob_start();
// Add date selector.
$current_date = current_time( 'd M Y' );
$post_date_from = isset( $_REQUEST['post-date-filter-from'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-from'] ) ) : $current_date; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
echo '<input type="text" id="datepicker-from" name="post-date-filter-from" value="' . esc_attr( $post_date_from ) . '" size="11" />';
$post_date_to = isset( $_REQUEST['post-date-filter-to'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-to'] ) ) : $current_date; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
echo '<input type="text" id="datepicker-to" name="post-date-filter-to" value="' . esc_attr( $post_date_to ) . '" size="11" />';
$output = ob_get_clean();
if ( ! empty( $output ) ) {
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'top-10-query-submit' ) );
}
}
?>
</div>
<?php
}
}

View File

@@ -0,0 +1,139 @@
<?php
/**
* Top 10 Display Network statistics page.
*
* @package Top_Ten
* @subpackage Top_Ten_Network_Statistics
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
/**
* Top_Ten_Network_Statistics class.
*/
class Top_Ten_Network_Statistics {
/**
* Class instance.
*
* @var class Class instance.
*/
public static $instance;
/**
* WP_List_Table object.
*
* @var object WP_List_Table object.
*/
public $pop_posts_obj;
/**
* Class constructor.
*
* @access public
* @return void
*/
public function __construct() {
add_filter( 'set-screen-option', array( __CLASS__, 'set_screen' ), 10, 3 );
}
/**
* Set screen.
*
* @param string $status Status of screen.
* @param string $option Option name.
* @param string $value Option value.
* @return string Value.
*/
public static function set_screen( $status, $option, $value ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
return $value;
}
/**
* Plugin settings page
*/
public function plugin_settings_page() {
$args = null;
if ( isset( $_REQUEST['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$page = sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
?>
<div class="wrap">
<h1><?php esc_html_e( 'Top 10 - Network Wide Popular Posts', 'top-10' ); ?></h1>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="get">
<input type="hidden" name="page" value="<?php echo esc_attr( $page ); ?>" />
<?php
// If this is a post date filter?
if ( isset( $_REQUEST['post-date-filter-to'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['post-date-filter-to'] = sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-to'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
if ( isset( $_REQUEST['post-date-filter-from'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['post-date-filter-from'] = sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-from'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
$this->pop_posts_obj->prepare_items( $args );
$this->pop_posts_obj->display();
?>
</form>
</div>
</div>
<div id="postbox-container-1" class="postbox-container">
<div id="side-sortables" class="meta-box-sortables ui-sortable">
<?php include_once 'sidebar.php'; ?>
</div><!-- /side-sortables -->
</div><!-- /postbox-container-1 -->
</div><!-- /post-body -->
<br class="clear" />
</div><!-- /poststuff -->
</div>
<?php
}
/**
* Screen options
*/
public function screen_option() {
$option = 'per_page';
$args = array(
'label' => __( 'Popular Posts', 'top-10' ),
'default' => 20,
'option' => 'pop_posts_per_page',
);
add_screen_option( $option, $args );
$this->pop_posts_obj = new Top_Ten_Network_Statistics_Table();
}
/** Singleton instance */
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
/**
* Function to initialise stats page.
*
* @since 2.4.2
*/
function tptn_network_stats_page() {
Top_Ten_Statistics::get_instance();
}
add_action( 'plugins_loaded', 'tptn_network_stats_page' );

View File

@@ -0,0 +1,512 @@
<?php
/**
* Top 10 Display statistics table.
*
* @package Top_Ten
* @subpackage Top_Ten_Statistics_Table
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
/**
* Top_Ten_Statistics_Table class.
*
* @extends WP_List_Table
*/
class Top_Ten_Statistics_Table extends WP_List_Table {
/**
* Holds the post type array elements for translation.
*
* @var array
*/
public $all_post_type;
/**
* Class constructor.
*/
public function __construct() {
parent::__construct(
array(
'singular' => __( 'popular_post', 'top-10' ), // Singular name of the listed records.
'plural' => __( 'popular_posts', 'top-10' ), // plural name of the listed records.
)
);
$this->all_post_type = array(
'all' => __( 'All post types', 'top-10' ),
);
}
/**
* Retrieve the Top 10 posts
*
* @param int $per_page Posts per page.
* @param int $page_number Page number.
* @param array $args Array of arguments.
*
* @return array Array of popular posts
*/
public function get_popular_posts( $per_page = 20, $page_number = 1, $args = null ) {
global $wpdb;
$blog_id = get_current_blog_id();
$from_date = isset( $args['post-date-filter-from'] ) ? $args['post-date-filter-from'] : current_time( 'd M Y' );
$from_date = gmdate( 'Y-m-d', strtotime( $from_date ) );
$to_date = isset( $args['post-date-filter-to'] ) ? $args['post-date-filter-to'] : current_time( 'd M Y' );
$to_date = gmdate( 'Y-m-d', strtotime( $to_date ) );
/* Start creating the SQL */
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily AS ttd';
$table_name = $wpdb->base_prefix . 'top_ten AS ttt';
// Fields to return.
$fields[] = 'ID';
$fields[] = 'post_title as title';
$fields[] = 'post_type';
$fields[] = 'post_date';
$fields[] = 'post_author';
$fields[] = 'ttt.cntaccess as total_count';
$fields[] = 'SUM(ttd.cntaccess) as daily_count';
$fields = implode( ', ', $fields );
// Create the JOIN clause.
$join = " INNER JOIN {$wpdb->posts} ON ttt.postnumber=ID ";
$join .= $wpdb->prepare(
" LEFT JOIN (
SELECT * FROM {$table_name_daily} " . // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
'WHERE DATE(ttd.dp_date) >= DATE(%s) AND DATE(ttd.dp_date) <= DATE(%s)
) AS ttd
ON ttt.postnumber=ttd.postnumber
',
$from_date,
$to_date
);
// Create the base WHERE clause.
$where = $wpdb->prepare( ' AND ttt.blog_id = %d ', $blog_id ); // Posts need to be from the current blog only.
$where .= " AND ($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_status = 'inherit') "; // Show published posts and attachments.
$where .= " AND ($wpdb->posts.post_type <> 'revision' ) "; // No revisions.
/* If search argument is set, do a search for it. */
if ( ! empty( $args['search'] ) ) {
$where .= $wpdb->prepare( " AND $wpdb->posts.post_title LIKE %s ", '%' . $wpdb->esc_like( $args['search'] ) . '%' );
}
/* If post filter argument is set, do a search for it. */
if ( isset( $args['post-type-filter'] ) && $this->all_post_type['all'] !== $args['post-type-filter'] ) {
$where .= $wpdb->prepare( " AND $wpdb->posts.post_type = %s ", $args['post-type-filter'] );
}
// Create the base GROUP BY clause.
$groupby = ' ID ';
// Create the base ORDER BY clause.
$orderby = ' total_count DESC ';
if ( ! empty( $_REQUEST['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$orderby = sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! in_array( $orderby, array( 'title', 'daily_count', 'total_count' ) ) ) { //phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
$orderby = ' total_count ';
}
if ( ! empty( $_REQUEST['order'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$order = sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( in_array( $order, array( 'asc', 'ASC', 'desc', 'DESC' ) ) ) { //phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
$orderby .= ' ' . $order;
} else {
$orderby .= ' DESC';
}
}
}
// Create the base LIMITS clause.
$limits = $wpdb->prepare( ' LIMIT %d, %d ', ( $page_number - 1 ) * $per_page, $per_page );
if ( ! empty( $groupby ) ) {
$groupby = " GROUP BY {$groupby} ";
}
if ( ! empty( $orderby ) ) {
$orderby = " ORDER BY {$orderby} ";
}
$sql = "SELECT $fields FROM {$table_name} $join WHERE 1=1 $where $groupby $orderby $limits";
$result = $wpdb->get_results( $sql, 'ARRAY_A' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
return $result;
}
/**
* Delete the post count for this post.
*
* @param int $id post ID.
*/
public static function delete_post_count( $id ) {
global $wpdb;
$wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
"{$wpdb->base_prefix}top_ten",
array(
'postnumber' => $id,
),
array( '%d' )
);
$wpdb->delete( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
"{$wpdb->base_prefix}top_ten_daily",
array(
'postnumber' => $id,
),
array( '%d' )
);
}
/**
* Returns the count of records in the database.
*
* @param string $args Array of arguments.
* @return null|string null|string
*/
public function record_count( $args = null ) {
global $wpdb;
$sql = $wpdb->prepare(
"
SELECT COUNT(*) FROM {$wpdb->base_prefix}top_ten as ttt
INNER JOIN {$wpdb->posts} ON ttt.postnumber=ID
WHERE blog_id=%d
AND ($wpdb->posts.post_status = 'publish' OR $wpdb->posts.post_status = 'inherit')
",
get_current_blog_id()
);
if ( isset( $args['search'] ) ) {
$sql .= $wpdb->prepare( " AND $wpdb->posts.post_title LIKE %s ", '%' . $wpdb->esc_like( $args['search'] ) . '%' );
}
if ( isset( $args['post-type-filter'] ) && $this->all_post_type['all'] !== $args['post-type-filter'] ) {
$sql .= $wpdb->prepare( " AND $wpdb->posts.post_type = %s ", $args['post-type-filter'] );
}
return $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Text displayed when no post data is available
*/
public function no_items() {
esc_html_e( 'No popular posts available.', 'top-10' );
}
/**
* Render a column when no column specific method exist.
*
* @param array $item Current item.
* @param string $column_name Column name.
*
* @return mixed
*/
public function column_default( $item, $column_name ) {
switch ( $column_name ) {
case 'post_type':
return $item[ $column_name ];
case 'daily_count':
return tptn_number_format_i18n( absint( $item[ $column_name ] ) );
default:
// Show the whole array for troubleshooting purposes.
return print_r( $item, true ); //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
}
/**
* Render the checkbox column.
*
* @param array $item Current item.
* @return string
*/
public function column_cb( $item ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
'bulk-delete',
$item['ID']
);
}
/**
* Render the title column.
*
* @param array $item Current item.
* @return string
*/
public function column_title( $item ) {
$delete_nonce = wp_create_nonce( 'tptn_delete_entry' );
$page = isset( $_REQUEST['page'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$actions = array(
'view' => sprintf( '<a href="%s" target="_blank">' . __( 'View', 'top-10' ) . '</a>', get_permalink( $item['ID'] ) ),
'edit' => sprintf( '<a href="%s">' . __( 'Edit', 'top-10' ) . '</a>', get_edit_post_link( $item['ID'] ) ),
'delete' => sprintf( '<a href="?page=%s&action=%s&post=%s&_wpnonce=%s">' . __( 'Delete', 'top-10' ) . '</a>', esc_attr( $page ), 'delete', absint( $item['ID'] ), $delete_nonce ),
);
// Return the title contents.
return sprintf(
'<a href="%4$s">%1$s</a> <span style="color:silver">(id:%2$s)</span>%3$s',
$item['title'],
$item['ID'],
$this->row_actions( $actions ),
get_edit_post_link( $item['ID'] )
);
}
/**
* Handles the post date column output.
*
* @param array $item Current item.
* @return void
*/
public function column_date( $item ) {
$m_time = $item['post_date'];
$time = get_post_time( 'G', true, $item['ID'] );
$time_diff = time() - $time;
if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS ) {
/* translators: 1. Human time difference. */
$h_time = sprintf( __( '%s ago' ), human_time_diff( $time ) );
} else {
$h_time = mysql2date( __( 'Y/m/d' ), $m_time );
}
echo '<abbr title="' . esc_attr( $h_time ) . '">' . esc_attr( $h_time ) . '</abbr>';
}
/**
* Handles the post author column output.
*
* @param array $item Current item.
* @return void
*/
public function column_author( $item ) {
$author_info = get_userdata( $item['post_author'] );
$author_name = ( false === $author_info ) ? '' : ucwords( trim( stripslashes( $author_info->display_name ) ) );
printf(
'<a href="%s">%s</a>',
esc_url(
add_query_arg(
array(
'post_type' => $item['post_type'],
'author' => ( false === $author_info ) ? 0 : $author_info->ID,
),
'edit.php'
)
),
esc_html( $author_name )
);
}
/**
* Render the Total Count column.
*
* @param array $item Current item.
* @return string
*/
public function column_total_count( $item ) {
return sprintf(
'<div contentEditable="true" class="live_edit" id="total_count_%1$s" data-wp-post-id="%1$s" data-wp-count="%2$s">%3$s</div>',
$item['ID'],
$item['total_count'],
tptn_number_format_i18n( absint( $item['total_count'] ) )
);
}
/**
* Associative array of columns
*
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'title' => __( 'Title', 'top-10' ),
'total_count' => __( 'Total visits', 'top-10' ),
'daily_count' => __( 'Daily visits', 'top-10' ),
'post_type' => __( 'Post type', 'top-10' ),
'author' => __( 'Author', 'top-10' ),
'date' => __( 'Date', 'top-10' ),
);
/**
* Filter the columns displayed in the Posts list table.
*
* @since 1.5.0
*
* @param array $columns An array of column names.
*/
return apply_filters( 'manage_pop_posts_columns', $columns );
}
/**
* Columns to make sortable.
*
* @return array
*/
public function get_sortable_columns() {
$sortable_columns = array(
'title' => array( 'title', false ),
'total_count' => array( 'total_count', false ),
'daily_count' => array( 'daily_count', false ),
);
return $sortable_columns;
}
/**
* Returns an associative array containing the bulk action
*
* @return array
*/
public function get_bulk_actions() {
$actions = array(
'bulk-delete' => __( 'Delete Count', 'top-10' ),
);
return $actions;
}
/**
* Handles data query and filter, sorting, and pagination.
*
* @param array $args Array of arguments.
*/
public function prepare_items( $args = null ) {
$this->_column_headers = $this->get_column_info();
/** Process bulk action */
$this->process_bulk_action();
$per_page = $this->get_items_per_page( 'pop_posts_per_page', 20 );
$current_page = $this->get_pagenum();
$total_items = self::record_count( $args );
$this->set_pagination_args(
array(
'total_items' => $total_items, // WE have to calculate the total number of items.
'per_page' => $per_page, // WE have to determine how many items to show on a page.
'total_pages' => ceil( $total_items / $per_page ), // WE have to calculate the total number of pages.
)
);
$this->items = self::get_popular_posts( $per_page, $current_page, $args );
}
/**
* Handles any bulk actions
*/
public function process_bulk_action() {
// Detect when a bulk action is being triggered...
if ( 'delete' === $this->current_action() ) {
// In our file that handles the request, verify the nonce.
$postid = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'tptn_delete_entry' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
self::delete_post_count( $postid );
} else {
die( esc_html__( 'Are you sure you want to do this', 'top-10' ) );
}
}
// If the delete bulk action is triggered.
if ( ( isset( $_REQUEST['action'] ) && 'bulk-delete' === $_REQUEST['action'] )
|| ( isset( $_REQUEST['action2'] ) && 'bulk-delete' === $_REQUEST['action2'] )
) {
$delete_ids = isset( $_REQUEST['bulk-delete'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['bulk-delete'] ) ) : array();
// Loop over the array of record IDs and delete them.
foreach ( $delete_ids as $id ) {
self::delete_post_count( $id );
}
}
}
/**
* Adds extra navigation elements to the table.
*
* @param string $which Which part of the table are we.
*/
public function extra_tablenav( $which ) {
?>
<div class="alignleft actions">
<?php
if ( 'top' === $which ) {
ob_start();
// Add date selector.
$current_date = current_time( 'd M Y' );
$post_date_from = isset( $_REQUEST['post-date-filter-from'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-from'] ) ) : $current_date; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
echo '<input type="text" id="datepicker-from" name="post-date-filter-from" value="' . esc_attr( $post_date_from ) . '" size="11" />';
$post_date_to = isset( $_REQUEST['post-date-filter-to'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-to'] ) ) : $current_date; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
echo '<input type="text" id="datepicker-to" name="post-date-filter-to" value="' . esc_attr( $post_date_to ) . '" size="11" />';
$post_types = get_post_types(
array(
'public' => true,
)
);
$post_types = $this->all_post_type + $post_types;
if ( $post_types ) {
echo '<select name="post-type-filter">';
foreach ( $post_types as $post_type ) {
$selected = '';
if ( isset( $_REQUEST['post-type-filter'] ) && $_REQUEST['post-type-filter'] === $post_type ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$selected = ' selected = "selected"';
}
?>
<option value="<?php echo esc_attr( $post_type ); ?>" <?php echo esc_attr( $selected ); ?>><?php echo esc_attr( $post_type ); ?></option>
<?php
}
echo '</select>';
}
$output = ob_get_clean();
if ( ! empty( $output ) ) {
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'top-10-query-submit' ) );
}
}
?>
</div>
<?php
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* Top 10 Display statistics page.
*
* @package Top_Ten
* @subpackage Top_Ten_Statistics
*/
/**** If this file is called directly, abort. ****/
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
/**
* Top_Ten_Statistics class.
*/
class Top_Ten_Statistics {
/**
* Class instance.
*
* @var class Class instance.
*/
public static $instance;
/**
* WP_List_Table object.
*
* @var object WP_List_Table object.
*/
public $pop_posts_obj;
/**
* Class constructor.
*
* @access public
* @return void
*/
public function __construct() {
add_filter( 'set-screen-option', array( __CLASS__, 'set_screen' ), 10, 3 );
}
/**
* Set screen.
*
* @param string $status Status of screen.
* @param string $option Option name.
* @param string $value Option value.
* @return string Value.
*/
public static function set_screen( $status, $option, $value ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
return $value;
}
/**
* Plugin settings page
*/
public function plugin_settings_page() {
$args = null;
if ( isset( $_REQUEST['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$page = sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
?>
<div class="wrap">
<h1><?php esc_html_e( 'Top 10 Popular Posts', 'top-10' ); ?></h1>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<form method="get">
<input type="hidden" name="page" value="<?php echo esc_attr( $page ); ?>" />
<?php
// If this is a search?
if ( isset( $_REQUEST['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['search'] = sanitize_text_field( wp_unslash( $_REQUEST['s'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
// If this is a post type filter?
if ( isset( $_REQUEST['post-type-filter'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['post-type-filter'] = sanitize_text_field( wp_unslash( $_REQUEST['post-type-filter'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
// If this is a post date filter?
if ( isset( $_REQUEST['post-date-filter-to'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['post-date-filter-to'] = sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-to'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
if ( isset( $_REQUEST['post-date-filter-from'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$args['post-date-filter-from'] = sanitize_text_field( wp_unslash( $_REQUEST['post-date-filter-from'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
$this->pop_posts_obj->prepare_items( $args );
$this->pop_posts_obj->search_box( __( 'Search Table', 'top-10' ), 'top-10' );
$this->pop_posts_obj->display();
?>
</form>
</div>
</div>
<div id="postbox-container-1" class="postbox-container">
<div id="side-sortables" class="meta-box-sortables ui-sortable">
<?php include_once 'sidebar.php'; ?>
</div><!-- /side-sortables -->
</div><!-- /postbox-container-1 -->
</div><!-- /post-body -->
<br class="clear" />
</div><!-- /poststuff -->
</div>
<?php
}
/**
* Screen options
*/
public function screen_option() {
$option = 'per_page';
$args = array(
'label' => __( 'Popular Posts', 'top-10' ),
'default' => 20,
'option' => 'pop_posts_per_page',
);
add_screen_option( $option, $args );
$this->pop_posts_obj = new Top_Ten_Statistics_Table();
}
/** Singleton instance */
public static function get_instance() {
if ( ! isset( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
}
/**
* Function to initialise stats page.
*
* @since 2.4.2
*/
function tptn_stats_page() {
Top_Ten_Statistics::get_instance();
}
add_action( 'plugins_loaded', 'tptn_stats_page' );

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,692 @@
/*! jQuery UI - v1.12.1 - 2019-02-05
* http://jqueryui.com
* Includes: core.css, datepicker.css, theme.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=smoothness&cornerRadiusShadow=8px&offsetLeftShadow=-8px&offsetTopShadow=-8px&thicknessShadow=8px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=aaaaaa&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cd0a0a&fcError=cd0a0a&borderColorError=cd0a0a&bgImgOpacityError=95&bgTextureError=glass&bgColorError=fef1ec&iconColorHighlight=2e83ff&fcHighlight=363636&borderColorHighlight=fcefa1&bgImgOpacityHighlight=55&bgTextureHighlight=glass&bgColorHighlight=fbf9ee&iconColorActive=454545&fcActive=212121&borderColorActive=aaaaaa&bgImgOpacityActive=65&bgTextureActive=glass&bgColorActive=ffffff&iconColorHover=454545&fcHover=212121&borderColorHover=999999&bgImgOpacityHover=75&bgTextureHover=glass&bgColorHover=dadada&iconColorDefault=888888&fcDefault=555555&borderColorDefault=d3d3d3&bgImgOpacityDefault=75&bgTextureDefault=glass&bgColorDefault=e6e6e6&iconColorContent=222222&fcContent=222222&borderColorContent=aaaaaa&bgImgOpacityContent=75&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=222222&fcHeader=222222&borderColorHeader=aaaaaa&bgImgOpacityHeader=75&bgTextureHeader=highlight_soft&bgColorHeader=cccccc&cornerRadius=4px&fsDefault=1.1em&fwDefault=normal&ffDefault=Verdana%2CArial%2Csans-serif
* Copyright jQuery Foundation and other contributors; Licensed MIT */
/* Layout helpers
----------------------------------*/
.ui-helper-hidden {
display: none;
}
.ui-helper-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.ui-helper-reset {
margin: 0;
padding: 0;
border: 0;
outline: 0;
line-height: 1.3;
text-decoration: none;
font-size: 100%;
list-style: none;
}
.ui-helper-clearfix:before,
.ui-helper-clearfix:after {
content: "";
display: table;
border-collapse: collapse;
}
.ui-helper-clearfix:after {
clear: both;
}
.ui-helper-zfix {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
filter:Alpha(Opacity=0); /* support: IE8 */
}
.ui-front {
z-index: 100;
}
/* Interaction Cues
----------------------------------*/
.ui-state-disabled {
cursor: default !important;
pointer-events: none;
}
/* Icons
----------------------------------*/
.ui-icon {
display: inline-block;
vertical-align: middle;
margin-top: -.25em;
position: relative;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
}
.ui-widget-icon-block {
left: 50%;
margin-left: -8px;
display: block;
}
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ui-datepicker {
width: 17em;
padding: .2em .2em 0;
display: none;
}
.ui-datepicker .ui-datepicker-header {
position: relative;
padding: .2em 0;
}
.ui-datepicker .ui-datepicker-prev,
.ui-datepicker .ui-datepicker-next {
position: absolute;
top: 2px;
width: 1.8em;
height: 1.8em;
}
.ui-datepicker .ui-datepicker-prev-hover,
.ui-datepicker .ui-datepicker-next-hover {
top: 1px;
}
.ui-datepicker .ui-datepicker-prev {
left: 2px;
}
.ui-datepicker .ui-datepicker-next {
right: 2px;
}
.ui-datepicker .ui-datepicker-prev-hover {
left: 1px;
}
.ui-datepicker .ui-datepicker-next-hover {
right: 1px;
}
.ui-datepicker .ui-datepicker-prev span,
.ui-datepicker .ui-datepicker-next span {
display: block;
position: absolute;
left: 50%;
margin-left: -8px;
top: 50%;
margin-top: -8px;
}
.ui-datepicker .ui-datepicker-title {
margin: 0 2.3em;
line-height: 1.8em;
text-align: center;
}
.ui-datepicker .ui-datepicker-title select {
font-size: 1em;
margin: 1px 0;
}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year {
width: 45%;
}
.ui-datepicker table {
width: 100%;
font-size: .9em;
border-collapse: collapse;
margin: 0 0 .4em;
}
.ui-datepicker th {
padding: .7em .3em;
text-align: center;
font-weight: bold;
border: 0;
}
.ui-datepicker td {
border: 0;
padding: 1px;
}
.ui-datepicker td span,
.ui-datepicker td a {
display: block;
padding: .2em;
text-align: right;
text-decoration: none;
}
.ui-datepicker .ui-datepicker-buttonpane {
background-image: none;
margin: .7em 0 0 0;
padding: 0 .2em;
border-left: 0;
border-right: 0;
border-bottom: 0;
}
.ui-datepicker .ui-datepicker-buttonpane button {
float: right;
margin: .5em .2em .4em;
cursor: pointer;
padding: .2em .6em .3em .6em;
width: auto;
overflow: visible;
}
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
float: left;
}
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi {
width: auto;
}
.ui-datepicker-multi .ui-datepicker-group {
float: left;
}
.ui-datepicker-multi .ui-datepicker-group table {
width: 95%;
margin: 0 auto .4em;
}
.ui-datepicker-multi-2 .ui-datepicker-group {
width: 50%;
}
.ui-datepicker-multi-3 .ui-datepicker-group {
width: 33.3%;
}
.ui-datepicker-multi-4 .ui-datepicker-group {
width: 25%;
}
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
border-left-width: 0;
}
.ui-datepicker-multi .ui-datepicker-buttonpane {
clear: left;
}
.ui-datepicker-row-break {
clear: both;
width: 100%;
font-size: 0;
}
/* RTL support */
.ui-datepicker-rtl {
direction: rtl;
}
.ui-datepicker-rtl .ui-datepicker-prev {
right: 2px;
left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next {
left: 2px;
right: auto;
}
.ui-datepicker-rtl .ui-datepicker-prev:hover {
right: 1px;
left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next:hover {
left: 1px;
right: auto;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane {
clear: right;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button {
float: left;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
.ui-datepicker-rtl .ui-datepicker-group {
float: right;
}
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
border-right-width: 0;
border-left-width: 1px;
}
/* Icons */
.ui-datepicker .ui-icon {
display: block;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
left: .5em;
top: .3em;
}
.ui-datepicker {
border: 1px solid #aaaaaa;
background: #ffffff;
color: #222222;
}
.ui-datepicker a {
color: #222222;
}
/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default,
.ui-button,
/* We use html here because we need a greater specificity to make sure disabled
works properly when clicked or hovered */
html .ui-button.ui-state-disabled:hover,
html .ui-button.ui-state-disabled:active {
border: 1px solid #d3d3d3;
background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;
font-weight: normal;
color: #555555;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited,
a.ui-button,
a:link.ui-button,
a:visited.ui-button,
.ui-button {
color: #555555;
text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus,
.ui-button:hover,
.ui-button:focus {
border: 1px solid #999999;
background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited,
.ui-state-focus a,
.ui-state-focus a:hover,
.ui-state-focus a:link,
.ui-state-focus a:visited,
a.ui-button:hover,
a.ui-button:focus {
color: #212121;
text-decoration: none;
}
.ui-visual-focus {
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active,
a.ui-button:active,
.ui-button:active,
.ui-button.ui-state-active:hover {
border: 1px solid #aaaaaa;
background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;
font-weight: normal;
color: #212121;
}
.ui-icon-background,
.ui-state-active .ui-icon-background {
border: #aaaaaa;
background-color: #212121;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
color: #212121;
text-decoration: none;
}
/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
border: 1px solid #fcefa1;
background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;
color: #363636;
}
.ui-state-checked {
border: 1px solid #fcefa1;
background: #fbf9ee;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
color: #363636;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
border: 1px solid #cd0a0a;
background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;
color: #cd0a0a;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
color: #cd0a0a;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
color: #cd0a0a;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
opacity: .7;
filter:Alpha(Opacity=70); /* support: IE8 */
font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
opacity: .35;
filter:Alpha(Opacity=35); /* support: IE8 */
background-image: none;
}
.ui-state-disabled .ui-icon {
filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
width: 16px;
height: 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-widget-header .ui-icon {
background-image: url("images/ui-icons_222222_256x240.png");
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon,
.ui-button:hover .ui-icon,
.ui-button:focus .ui-icon {
background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-active .ui-icon,
.ui-button:active .ui-icon {
background-image: url("images/ui-icons_454545_256x240.png");
}
.ui-state-highlight .ui-icon,
.ui-button .ui-state-highlight.ui-icon {
background-image: url("images/ui-icons_2e83ff_256x240.png");
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
background-image: url("images/ui-icons_cd0a0a_256x240.png");
}
.ui-button .ui-icon {
background-image: url("images/ui-icons_888888_256x240.png");
}
/* positioning */
.ui-icon-blank { background-position: 16px 16px; }
.ui-icon-caret-1-n { background-position: 0 0; }
.ui-icon-caret-1-ne { background-position: -16px 0; }
.ui-icon-caret-1-e { background-position: -32px 0; }
.ui-icon-caret-1-se { background-position: -48px 0; }
.ui-icon-caret-1-s { background-position: -65px 0; }
.ui-icon-caret-1-sw { background-position: -80px 0; }
.ui-icon-caret-1-w { background-position: -96px 0; }
.ui-icon-caret-1-nw { background-position: -112px 0; }
.ui-icon-caret-2-n-s { background-position: -128px 0; }
.ui-icon-caret-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -65px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -65px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
border-top-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
border-top-right-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
border-bottom-left-radius: 4px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
border-bottom-right-radius: 4px;
}
/* Overlays */
.ui-widget-overlay {
background: #aaaaaa;
opacity: .3;
filter: Alpha(Opacity=30); /* support: IE8 */
}
.ui-widget-shadow {
-webkit-box-shadow: -8px -8px 8px #aaaaaa;
box-shadow: -8px -8px 8px #aaaaaa;
}
/* Live editing styles
----------------------------------*/
.live_edit {
padding: 0 2px;
}
.live_edit_mode {
border: 1px solid black;
}
.live_edit_mode_success {
background-color: lightgreen;
-webkit-transition: background-color 0.5s ease;
-moz-transition: background-color 0.5s ease;
-o-transition: background-color 0.5s ease;
transition: background-color 0.5s ease;
}
.live_edit_mode_error {
background-color: lightpink;
-webkit-transition: background-color 0.5s ease;
-moz-transition: background-color 0.5s ease;
-o-transition: background-color 0.5s ease;
transition: background-color 0.5s ease;
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
.ui-autocomplete {
z-index: 9999999999;
}

View File

@@ -0,0 +1 @@
.ui-autocomplete{z-index:9999999999}

View File

@@ -0,0 +1,911 @@
<?php
/**
* Default settings.
*
* Functions to register the default settings of the plugin.
*
* @link https://webberzone.com
* @since 2.6.0
*
* @package Top 10
* @subpackage Admin/Register_Settings
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Retrieve the array of plugin settings
*
* @since 2.5.0
*
* @return array Settings array
*/
function tptn_get_registered_settings() {
$tptn_settings = array(
'general' => tptn_settings_general(),
'counter' => tptn_settings_counter(),
'list' => tptn_settings_list(),
'thumbnail' => tptn_settings_thumbnail(),
'styles' => tptn_settings_styles(),
'maintenance' => tptn_settings_maintenance(),
'feed' => tptn_settings_feed(),
);
/**
* Filters the settings array
*
* @since 2.5.0
*
* @param array $tptn_settings Settings array
*/
return apply_filters( 'tptn_registered_settings', $tptn_settings );
}
/**
* Retrieve the array of General settings
*
* @since 2.6.0
*
* @return array General settings array
*/
function tptn_settings_general() {
$settings = array(
'trackers' => array(
'id' => 'trackers',
'name' => esc_html__( 'Enable trackers', 'top-10' ),
/* translators: 1: Code. */
'desc' => '',
'type' => 'multicheck',
'default' => array(
'overall' => 'overall',
'daily' => 'daily',
),
'options' => array(
'overall' => esc_html__( 'Overall', 'top-10' ),
'daily' => esc_html__( 'Daily', 'top-10' ),
),
),
'cache' => array(
'id' => 'cache',
'name' => esc_html__( 'Enable cache', 'top-10' ),
'desc' => esc_html__( 'If activated, Top 10 will use the Transients API to cache the popular posts output for 1 hour.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
'cache_time' => array(
'id' => 'cache_time',
'name' => esc_html__( 'Time to cache', 'top-10' ),
'desc' => esc_html__( 'Enter the number of seconds to cache the output.', 'top-10' ),
'type' => 'text',
'options' => HOUR_IN_SECONDS,
),
'daily_midnight' => array(
'id' => 'daily_midnight',
'name' => esc_html__( 'Start daily counts from midnight', 'top-10' ),
'desc' => esc_html__( 'Daily counter will display number of visits from midnight. This option is checked by default and mimics the way most normal counters work. Turning this off will allow you to use the hourly setting in the next option.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'range_desc' => array(
'id' => 'range_desc',
'name' => '<strong>' . esc_html__( 'Default custom period range', 'top-10' ) . '</strong>',
'desc' => esc_html__( 'The next two options allow you to set the default range for the custom period. This was previously called the daily range. This can be overridden in the widget.', 'top-10' ),
'type' => 'descriptive_text',
),
'daily_range' => array(
'id' => 'daily_range',
'name' => esc_html__( 'Day(s)', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '1',
'min' => '0',
'size' => 'small',
),
'hour_range' => array(
'id' => 'hour_range',
'name' => esc_html__( 'Hour(s)', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '0',
'min' => '0',
'max' => '23',
'size' => 'small',
),
'uninstall_clean_options' => array(
'id' => 'uninstall_clean_options',
'name' => esc_html__( 'Delete options on uninstall', 'top-10' ),
'desc' => esc_html__( 'If this is checked, all settings related to Top 10 are removed from the database if you choose to uninstall/delete the plugin.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'uninstall_clean_tables' => array(
'id' => 'uninstall_clean_tables',
'name' => esc_html__( 'Delete counter data on uninstall', 'top-10' ),
'desc' => esc_html__( 'If this is checked, the tables containing the counter statistics are removed from the database if you choose to uninstall/delete the plugin. Keep this unchecked if you choose to reinstall the plugin and do not want to lose your counter data.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
'show_metabox' => array(
'id' => 'show_metabox',
'name' => esc_html__( 'Show metabox', 'top-10' ),
'desc' => esc_html__( 'This will add the Top 10 metabox on Edit Posts or Add New Posts screens. Also applies to Pages and Custom Post Types.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'show_metabox_admins' => array(
'id' => 'show_metabox_admins',
'name' => esc_html__( 'Limit meta box to Admins only', 'top-10' ),
'desc' => esc_html__( 'If selected, the meta box will be hidden from anyone who is not an Admin. By default, Contributors and above will be able to see the meta box. Applies only if the above option is selected.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
'show_credit' => array(
'id' => 'show_credit',
'name' => esc_html__( 'Link to Top 10 plugin page', 'top-10' ),
'desc' => esc_html__( 'A no-follow link to the plugin homepage will be added as the last item of the popular posts.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
);
/**
* Filters the General settings array
*
* @since 2.6.0
*
* @param array $settings General settings array
*/
return apply_filters( 'tptn_settings_general', $settings );
}
/**
* Retrieve the array of Counter settings
*
* @since 2.6.0
*
* @return array Counter settings array
*/
function tptn_settings_counter() {
$settings = array(
'add_to' => array(
'id' => 'add_to',
'name' => esc_html__( 'Display number of views on', 'top-10' ) . ':',
/* translators: 1: Code. */
'desc' => sprintf( esc_html__( 'If you choose to disable this, please add %1$s to your template file where you want it displayed', 'top-10' ), "<code>&lt;?php if ( function_exists( 'echo_tptn_post_count' ) ) { echo_tptn_post_count(); } ?&gt;</code>" ),
'type' => 'multicheck',
'default' => array(
'single' => 'single',
'page' => 'page',
),
'options' => array(
'single' => esc_html__( 'Posts', 'top-10' ),
'page' => esc_html__( 'Pages', 'top-10' ),
'home' => esc_html__( 'Home page', 'top-10' ),
'feed' => esc_html__( 'Feeds', 'top-10' ),
'category_archives' => esc_html__( 'Category archives', 'top-10' ),
'tag_archives' => esc_html__( 'Tag archives', 'top-10' ),
'other_archives' => esc_html__( 'Other archives', 'top-10' ),
),
),
'count_disp_form' => array(
'id' => 'count_disp_form',
'name' => esc_html__( 'Format to display the post views', 'top-10' ),
/* translators: 1: Opening a tag, 2: Closing a tag, 3: Opening code tage, 4. Closing code tag. */
'desc' => sprintf( esc_html__( 'Use %1$s to display the total count, %2$s for daily count and %3$s for overall counts across all posts. Default display is %4$s', 'top-10' ), '<code>%totalcount%</code>', '<code>%dailycount%</code>', '<code>%overallcount%</code>', '<code>(Visited %totalcount% times, %dailycount% visits today)</code>' ),
'type' => 'textarea',
'options' => '(Visited %totalcount% times, %dailycount% visits today)',
),
'count_disp_form_zero' => array(
'id' => 'count_disp_form_zero',
'name' => esc_html__( 'What to display when there are no visits?', 'top-10' ),
/* translators: 1: Opening a tag, 2: Closing a tag, 3: Opening code tage, 4. Closing code tag. */
'desc' => esc_html__( "This text applies only when there are 0 hits for the post and it isn't a single page. e.g. if you display post views on the homepage or archives then this text will be used. To override this, just enter the same text as above option.", 'top-10' ),
'type' => 'textarea',
'options' => 'No visits yet',
),
'number_format_count' => array(
'id' => 'number_format_count',
'name' => esc_html__( 'Number format post count', 'top-10' ),
'desc' => esc_html__( 'Activating this option will convert the post counts into a number format based on the locale', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'dynamic_post_count' => array(
'id' => 'dynamic_post_count',
'name' => esc_html__( 'Always display latest post count', 'top-10' ),
'desc' => esc_html__( 'This option uses JavaScript and will increase your page load time. Turn this off if you are not using caching plugins or are OK with displaying older cached counts.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
'tracker_type' => array(
'id' => 'tracker_type',
'name' => esc_html__( 'Tracker type', 'top-10' ),
'desc' => '',
'type' => 'radiodesc',
'default' => 'query_based',
'options' => tptn_get_tracker_types(),
),
'tracker_all_pages' => array(
'id' => 'tracker_all_pages',
'name' => esc_html__( 'Load tracker on all pages', 'top-10' ),
'desc' => esc_html__( 'This will load the tracker js on all pages. Helpful if you are running minification/concatenation plugins.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
'track_users' => array(
'id' => 'track_users',
'name' => esc_html__( 'Track user groups', 'top-10' ) . ':',
'desc' => esc_html__( 'Uncheck above to disable tracking if the current user falls into any one of these groups.', 'top-10' ),
'type' => 'multicheck',
'default' => array(
'editors' => 'editors',
'admins' => 'admins',
),
'options' => array(
'authors' => esc_html__( 'Authors', 'top-10' ),
'editors' => esc_html__( 'Editors', 'top-10' ),
'admins' => esc_html__( 'Admins', 'top-10' ),
),
),
'logged_in' => array(
'id' => 'logged_in',
'name' => esc_html__( 'Track logged-in users', 'top-10' ),
'desc' => esc_html__( 'Uncheck to stop tracking logged in users. Only logged out visitors will be tracked if this is disabled. Unchecking this will override the above setting.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'exclude_on_post_ids' => array(
'id' => 'exclude_on_post_ids',
'name' => esc_html__( 'Exclude display on these post IDs', 'top-10' ),
'desc' => esc_html__( 'Comma-separated list of post or page IDs to exclude displaying the top posts on. e.g. 188,320,500', 'top-10' ),
'type' => 'numbercsv',
'options' => '',
),
'pv_in_admin' => array(
'id' => 'pv_in_admin',
'name' => esc_html__( 'Page views in admin', 'top-10' ),
'desc' => esc_html__( "Adds three columns called Total Views, Today's Views and Views to All Posts and All Pages. You can selectively disable these by pulling down the Screen Options from the top right of the respective screens.", 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'show_count_non_admins' => array(
'id' => 'show_count_non_admins',
'name' => esc_html__( 'Show views to non-admins', 'top-10' ),
'desc' => esc_html__( "If you disable this then non-admins won't see the above columns or view the independent pages with the top posts.", 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'debug_mode' => array(
'id' => 'debug_mode',
'name' => esc_html__( 'Debug mode', 'top-10' ),
'desc' => esc_html__( 'Setting this to true will force the tracker to display an output in the browser. This is useful if you are having issues and are seeking support.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
);
/**
* Filters the Counter settings array
*
* @since 2.6.0
*
* @param array $settings Counter settings array
*/
return apply_filters( 'tptn_settings_counter', $settings );
}
/**
* Retrieve the array of List settings
*
* @since 2.6.0
*
* @return array List settings array
*/
function tptn_settings_list() {
$settings = array(
'limit' => array(
'id' => 'limit',
'name' => esc_html__( 'Number of posts to display', 'top-10' ),
'desc' => esc_html__( 'Maximum number of posts that will be displayed in the list. This option is used if you do not specify the number of posts in the widget or shortcodes', 'top-10' ),
'type' => 'number',
'options' => '10',
'size' => 'small',
),
'how_old' => array(
'id' => 'how_old',
'name' => esc_html__( 'Published age of posts', 'top-10' ),
'desc' => esc_html__( 'This options allows you to only show posts that have been published within the above day range. Applies to both overall posts and daily posts lists. e.g. 365 days will only show posts published in the last year in the popular posts lists. Enter 0 for no restriction.', 'top-10' ),
'type' => 'number',
'options' => '0',
),
'post_types' => array(
'id' => 'post_types',
'name' => esc_html__( 'Post types to include', 'top-10' ),
'desc' => esc_html__( 'At least one option should be selected above. Select which post types you want to include in the list of posts. This field can be overridden using a comma separated list of post types when using the manual display.', 'top-10' ),
'type' => 'posttypes',
'options' => 'post',
),
'exclude_front' => array(
'id' => 'exclude_front',
'name' => esc_html__( 'Exclude Front page and Posts page', 'top-10' ),
'desc' => esc_html__( 'If you have set your Front page and Posts page to be specific pages via Settings > Reading, then these will be tracked similar to other pages. Enable this option to exclude them from showing up in the popular posts lists. The tracking will not be disabled.', 'top-10' ),
'type' => 'checkbox',
'options' => false,
),
'exclude_post_ids' => array(
'id' => 'exclude_post_ids',
'name' => esc_html__( 'Post/page IDs to exclude', 'top-10' ),
'desc' => esc_html__( 'Comma-separated list of post or page IDs to exclude from the list. e.g. 188,320,500', 'top-10' ),
'type' => 'numbercsv',
'options' => '',
),
'exclude_cat_slugs' => array(
'id' => 'exclude_cat_slugs',
'name' => esc_html__( 'Exclude Categories', 'top-10' ),
'desc' => esc_html__( 'Comma separated list of category slugs. The field above has an autocomplete so simply start typing in the starting letters and it will prompt you with options. Does not support custom taxonomies.', 'top-10' ),
'type' => 'csv',
'options' => '',
'size' => 'large',
'field_class' => 'category_autocomplete',
'field_attributes' => array(
'data-wp-taxonomy' => 'category',
),
),
'exclude_categories' => array(
'id' => 'exclude_categories',
'name' => esc_html__( 'Exclude category IDs', 'top-10' ),
'desc' => esc_html__( 'This is a readonly field that is automatically populated based on the above input when the settings are saved. These might differ from the IDs visible in the Categories page which use the term_id. Top 10 uses the term_taxonomy_id which is unique to this taxonomy.', 'top-10' ),
'type' => 'text',
'options' => '',
'readonly' => true,
),
'customize_output_header' => array(
'id' => 'customize_output_header',
'name' => '<h3>' . esc_html__( 'Customize the output', 'top-10' ) . '</h3>',
'desc' => '',
'type' => 'header',
),
'title' => array(
'id' => 'title',
'name' => esc_html__( 'Heading of posts', 'top-10' ),
'desc' => esc_html__( 'Displayed before the list of the posts as a the master heading', 'top-10' ),
'type' => 'text',
'options' => '<h3>' . esc_html__( 'Popular posts:', 'top-10' ) . '</h3>',
'size' => 'large',
),
'title_daily' => array(
'id' => 'title_daily',
'name' => esc_html__( 'Heading of posts for daily/custom period lists', 'top-10' ),
'desc' => esc_html__( 'Displayed before the list of the posts as a the master heading', 'top-10' ),
'type' => 'text',
'options' => '<h3>' . esc_html__( 'Currently trending:', 'top-10' ) . '</h3>',
'size' => 'large',
),
'blank_output' => array(
'id' => 'blank_output',
'name' => esc_html__( 'Show when no posts are found', 'top-10' ),
/* translators: 1: Code. */
'desc' => '',
'type' => 'radio',
'default' => 'blank',
'options' => array(
'blank' => esc_html__( 'Blank output', 'top-10' ),
'custom_text' => esc_html__( 'Display custom text', 'top-10' ),
),
),
'blank_output_text' => array(
'id' => 'blank_output_text',
'name' => esc_html__( 'Custom text', 'top-10' ),
'desc' => esc_html__( 'Enter the custom text that will be displayed if the second option is selected above', 'top-10' ),
'type' => 'textarea',
'options' => esc_html__( 'No top posts yet', 'top-10' ),
),
'show_excerpt' => array(
'id' => 'show_excerpt',
'name' => esc_html__( 'Show post excerpt', 'top-10' ),
'desc' => '',
'type' => 'checkbox',
'options' => false,
),
'excerpt_length' => array(
'id' => 'excerpt_length',
'name' => esc_html__( 'Length of excerpt (in words)', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '10',
'size' => 'small',
),
'show_date' => array(
'id' => 'show_date',
'name' => esc_html__( 'Show date', 'top-10' ),
'desc' => '',
'type' => 'checkbox',
'options' => false,
),
'show_author' => array(
'id' => 'show_author',
'name' => esc_html__( 'Show author', 'top-10' ),
'desc' => '',
'type' => 'checkbox',
'options' => false,
),
'disp_list_count' => array(
'id' => 'disp_list_count',
'name' => esc_html__( 'Show number of views', 'top-10' ),
'desc' => '',
'type' => 'checkbox',
'options' => false,
),
'title_length' => array(
'id' => 'title_length',
'name' => esc_html__( 'Limit post title length (in characters)', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '60',
'size' => 'small',
),
'link_new_window' => array(
'id' => 'link_new_window',
'name' => esc_html__( 'Open links in new window', 'top-10' ),
'desc' => '',
'type' => 'checkbox',
'options' => false,
),
'link_nofollow' => array(
'id' => 'link_nofollow',
'name' => esc_html__( 'Add nofollow to links', 'top-10' ),
'desc' => '',
'type' => 'checkbox',
'options' => false,
),
'html_wrapper_header' => array(
'id' => 'html_wrapper_header',
'name' => '<h3>' . esc_html__( 'HTML to display', 'top-10' ) . '</h3>',
'desc' => '',
'type' => 'header',
),
'before_list' => array(
'id' => 'before_list',
'name' => esc_html__( 'Before the list of posts', 'top-10' ),
'desc' => '',
'type' => 'text',
'options' => '<ul>',
),
'after_list' => array(
'id' => 'after_list',
'name' => esc_html__( 'After the list of posts', 'top-10' ),
'desc' => '',
'type' => 'text',
'options' => '</ul>',
),
'before_list_item' => array(
'id' => 'before_list_item',
'name' => esc_html__( 'Before each list item', 'top-10' ),
'desc' => '',
'type' => 'text',
'options' => '<li>',
),
'after_list_item' => array(
'id' => 'after_list_item',
'name' => esc_html__( 'After each list item', 'top-10' ),
'desc' => '',
'type' => 'text',
'options' => '</li>',
),
);
/**
* Filters the List settings array
*
* @since 2.6.0
*
* @param array $settings List settings array
*/
return apply_filters( 'tptn_settings_list', $settings );
}
/**
* Retrieve the array of Thumbnail settings
*
* @since 2.6.0
*
* @return array Thumbnail settings array
*/
function tptn_settings_thumbnail() {
$settings = array(
'post_thumb_op' => array(
'id' => 'post_thumb_op',
'name' => esc_html__( 'Location of the post thumbnail', 'top-10' ),
'desc' => '',
'type' => 'radio',
'default' => 'text_only',
'options' => array(
'inline' => esc_html__( 'Display thumbnails inline with posts, before title', 'top-10' ),
'after' => esc_html__( 'Display thumbnails inline with posts, after title', 'top-10' ),
'thumbs_only' => esc_html__( 'Display only thumbnails, no text', 'top-10' ),
'text_only' => esc_html__( 'Do not display thumbnails, only text', 'top-10' ),
),
),
'thumb_size' => array(
'id' => 'thumb_size',
'name' => esc_html__( 'Thumbnail size', 'top-10' ),
/* translators: 1: OTF Regenerate plugin link, 2: Force regenerate plugin link. */
'desc' => esc_html__( 'You can choose from existing image sizes above or create a custom size. If you have chosen Custom size above, then enter the width, height and crop settings below. For best results, use a cropped image. If you change the width and/or height below, existing images will not be automatically resized.' ) . '<br />' . sprintf( esc_html__( 'I recommend using %1$s or %2$s to regenerate all image sizes.', 'top-10' ), '<a href="' . esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&amp;plugin=otf-regenerate-thumbnails&amp;TB_iframe=true&amp;width=600&amp;height=550' ) ) . '" class="thickbox">OTF Regenerate Thumbnails</a>', '<a href="' . esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&amp;plugin=regenerate-thumbnails&amp;TB_iframe=true&amp;width=600&amp;height=550' ) ) . '" class="thickbox">Regenerate Thumbnails</a>' ),
'type' => 'thumbsizes',
'default' => 'tptn_thumbnail',
'options' => tptn_get_all_image_sizes(),
),
'thumb_width' => array(
'id' => 'thumb_width',
'name' => esc_html__( 'Thumbnail width', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '250',
'size' => 'small',
),
'thumb_height' => array(
'id' => 'thumb_height',
'name' => esc_html__( 'Thumbnail height', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '250',
'size' => 'small',
),
'thumb_crop' => array(
'id' => 'thumb_crop',
'name' => esc_html__( 'Hard crop thumbnails', 'top-10' ),
'desc' => esc_html__( 'Check this box to hard crop the thumbnails. i.e. force the width and height above vs. maintaining proportions.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'thumb_create_sizes' => array(
'id' => 'thumb_create_sizes',
'name' => esc_html__( 'Generate thumbnail sizes', 'top-10' ),
'desc' => esc_html__( 'If you select this option and Custom size is selected above, the plugin will register the image size with WordPress to create new thumbnails. Does not update old images as explained above.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'thumb_html' => array(
'id' => 'thumb_html',
'name' => esc_html__( 'Thumbnail size attributes', 'top-10' ),
'desc' => '',
'type' => 'radio',
'default' => 'html',
'options' => array(
/* translators: %s: Code. */
'css' => sprintf( esc_html__( 'Use CSS to set the width and height: e.g. %s', 'top-10' ), '<code>style="max-width:250px;max-height:250px"</code>' ),
/* translators: %s: Code. */
'html' => sprintf( esc_html__( 'Use HTML attributes to set the width and height: e.g. %s', 'top-10' ), '<code>width="250" height="250"</code>' ),
'none' => esc_html__( 'No width or height set. You will need to use external styles to force any width or height of your choice.', 'top-10' ),
),
),
'thumb_meta' => array(
'id' => 'thumb_meta',
'name' => esc_html__( 'Thumbnail meta field name', 'top-10' ),
'desc' => esc_html__( 'The value of this field should contain the URL of the image and can be set in the metabox in the Edit Post screen', 'top-10' ),
'type' => 'text',
'options' => 'post-image',
),
'scan_images' => array(
'id' => 'scan_images',
'name' => esc_html__( 'Get first image', 'top-10' ),
'desc' => esc_html__( 'The plugin will fetch the first image in the post content if this is enabled. This can slow down the loading of your page if the first image in the followed posts is large in file-size.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'thumb_default_show' => array(
'id' => 'thumb_default_show',
'name' => esc_html__( 'Use default thumbnail?', 'top-10' ),
'desc' => esc_html__( 'If checked, when no thumbnail is found, show a default one from the URL below. If not checked and no thumbnail is found, no image will be shown.', 'top-10' ),
'type' => 'checkbox',
'options' => true,
),
'thumb_default' => array(
'id' => 'thumb_default',
'name' => esc_html__( 'Default thumbnail', 'top-10' ),
'desc' => esc_html__( 'Enter the full URL of the image that you wish to display if no thumbnail is found. This image will be displayed below.', 'top-10' ),
'type' => 'text',
'options' => TOP_TEN_PLUGIN_URL . 'default.png',
'size' => 'large',
),
);
/**
* Filters the Thumbnail settings array
*
* @since 2.6.0
*
* @param array $settings Thumbnail settings array
*/
return apply_filters( 'tptn_settings_thumbnail', $settings );
}
/**
* Retrieve the array of Styles settings
*
* @since 2.6.0
*
* @return array Styles settings array
*/
function tptn_settings_styles() {
$settings = array(
'tptn_styles' => array(
'id' => 'tptn_styles',
'name' => esc_html__( 'Popular posts style', 'top-10' ),
'desc' => '',
'type' => 'radiodesc',
'default' => 'no_style',
'options' => tptn_get_styles(),
),
'custom_css' => array(
'id' => 'custom_css',
'name' => esc_html__( 'Custom CSS', 'top-10' ),
/* translators: 1: Opening a tag, 2: Closing a tag, 3: Opening code tage, 4. Closing code tag. */
'desc' => sprintf( esc_html__( 'Do not include %3$sstyle%4$s tags. Check out the %1$sFAQ%2$s for available CSS classes to style.', 'top-10' ), '<a href="' . esc_url( 'https://wordpress.org/plugins/top-10/faq/' ) . '" target="_blank">', '</a>', '<code>', '</code>' ),
'type' => 'css',
'options' => '',
'field_class' => 'codemirror_css',
),
);
/**
* Filters the Styles settings array
*
* @since 2.6.0
*
* @param array $settings Styles settings array
*/
return apply_filters( 'tptn_settings_styles', $settings );
}
/**
* Retrieve the array of Maintenance settings
*
* @since 2.6.0
*
* @return array Maintenance settings array
*/
function tptn_settings_maintenance() {
$settings = array(
'cron_on' => array(
'id' => 'cron_on',
'name' => esc_html__( 'Enable scheduled maintenance', 'top-10' ),
/* translators: 1: Constant holding number of days data is stored. */
'desc' => sprintf( esc_html__( 'Cleaning the database at regular intervals could improve performance, especially on high traffic blogs. Enabling maintenance will automatically delete entries older than %d days in the daily tables.', 'top-10' ), TOP_TEN_STORE_DATA ),
'type' => 'checkbox',
'options' => false,
),
'cron_range_desc' => array(
'id' => 'cron_range_desc',
'name' => '<strong>' . esc_html__( 'Time to run maintenance', 'top-10' ) . '</strong>',
'desc' => esc_html__( 'The next two options allow you to set the time to run the cron.', 'top-10' ),
'type' => 'descriptive_text',
),
'cron_hour' => array(
'id' => 'cron_hour',
'name' => esc_html__( 'Hour', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '0',
'min' => '0',
'max' => '23',
'size' => 'small',
),
'cron_min' => array(
'id' => 'cron_min',
'name' => esc_html__( 'Minute', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '0',
'min' => '0',
'max' => '59',
'size' => 'small',
),
'cron_recurrence' => array(
'id' => 'cron_recurrence',
'name' => esc_html__( 'Run maintenance', 'top-10' ),
'desc' => '',
'type' => 'radio',
'default' => 'weekly',
'options' => array(
'daily' => esc_html__( 'Daily', 'top-10' ),
'weekly' => esc_html__( 'Weekly', 'top-10' ),
'fortnightly' => esc_html__( 'Fortnightly', 'top-10' ),
'monthly' => esc_html__( 'Monthly', 'top-10' ),
),
),
);
/**
* Filters the Maintenance settings array
*
* @since 2.6.0
*
* @param array $settings Maintenance settings array
*/
return apply_filters( 'tptn_settings_maintenance', $settings );
}
/**
* Retrieve the array of Feed settings
*
* @since 2.8.0
*
* @return array Feed settings array
*/
function tptn_settings_feed() {
$settings = array(
'feed_permalink_overall' => array(
'id' => 'feed_permalink_overall',
'name' => esc_html__( 'Permalink - Overall', 'top-10' ),
/* translators: 1: Opening link tag, 2: Closing link tag. */
'desc' => sprintf( esc_html__( 'This will set the path of the custom feed generated by the plugin for overall popular posts. You might need to %1$srefresh your permalinks%2$s when changing this option.', 'top-10' ), '<a href="' . admin_url( 'options-permalink.php' ) . '" target="_blank">', '</a>' ),
'type' => 'text',
'options' => 'popular-posts',
'size' => 'large',
),
'feed_permalink_daily' => array(
'id' => 'feed_permalink_daily',
'name' => esc_html__( 'Permalink - Daily', 'top-10' ),
/* translators: 1: Opening link tag, 2: Closing link tag. */
'desc' => sprintf( esc_html__( 'This will set the path of the custom feed generated by the plugin for daily/custom period popular posts. You might need to %1$srefresh your permalinks%2$s when changing this option.', 'top-10' ), '<a href="' . admin_url( 'options-permalink.php' ) . '" target="_blank">', '</a>' ),
'type' => 'text',
'options' => 'popular-posts-daily',
'size' => 'large',
),
'feed_limit' => array(
'id' => 'feed_limit',
'name' => esc_html__( 'Number of posts to display', 'top-10' ),
'desc' => esc_html__( 'Maximum number of posts that will be displayed in the custom feed.', 'top-10' ),
'type' => 'number',
'options' => '10',
'size' => 'small',
),
'feed_daily_range' => array(
'id' => 'feed_daily_range',
'name' => esc_html__( 'Custom period in day(s)', 'top-10' ),
'desc' => '',
'type' => 'number',
'options' => '1',
'min' => '0',
'size' => 'small',
),
);
/**
* Filters the Feed settings array
*
* @since 2.8.0
*
* @param array $settings Feed settings array
*/
return apply_filters( 'tptn_settings_feed', $settings );
}
/**
* Upgrade pre v2.5.0 settings.
*
* @since v2.5.0
* @return array Settings array
*/
function tptn_upgrade_settings() {
$old_settings = get_option( 'ald_tptn_settings' );
if ( empty( $old_settings ) ) {
return false;
}
// Start will assigning all the old settings to the new settings and we will unset later on.
$settings = $old_settings;
// Convert the add_to_{x} to the new settings format.
$add_to = array(
'single' => 'add_to_content',
'page' => 'count_on_pages',
'feed' => 'add_to_feed',
'home' => 'add_to_home',
'category_archives' => 'add_to_category_archives',
'tag_archives' => 'add_to_tag_archives',
'other_archives' => 'add_to_archives',
);
foreach ( $add_to as $newkey => $oldkey ) {
if ( $old_settings[ $oldkey ] ) {
$settings['add_to'][ $newkey ] = $newkey;
}
unset( $settings[ $oldkey ] );
}
// Convert the activate_overall and activate_daily to the new settings format.
$trackers = array(
'overall' => 'activate_overall',
'daily' => 'activate_daily',
);
foreach ( $trackers as $newkey => $oldkey ) {
if ( $old_settings[ $oldkey ] ) {
$settings['trackers'][ $newkey ] = $newkey;
}
unset( $settings[ $oldkey ] );
}
// Convert the track_{x} to the new settings format.
$track_users = array(
'authors' => 'track_authors',
'editors' => 'track_editors',
'admins' => 'track_admins',
);
foreach ( $track_users as $newkey => $oldkey ) {
if ( $old_settings[ $oldkey ] ) {
$settings['track_users'][ $newkey ] = $newkey;
}
unset( $settings[ $oldkey ] );
}
// Convert 'blank_output' to the new format: true = 'blank' and false = 'custom_text'.
$settings['blank_output'] = ! empty( $old_settings['blank_output'] ) ? 'blank' : 'custom_text';
$settings['custom_css'] = $old_settings['custom_CSS'];
return $settings;
}
/**
* Get the various styles.
*
* @since 2.5.0
* @return array Style options.
*/
function tptn_get_styles() {
$styles = array(
array(
'id' => 'no_style',
'name' => esc_html__( 'No styles', 'top-10' ),
'description' => esc_html__( 'Select this option if you plan to add your own styles', 'top-10' ) . '<br />',
),
array(
'id' => 'text_only',
'name' => esc_html__( 'Text only', 'top-10' ),
'description' => esc_html__( 'Disable thumbnails and no longer include the default style sheet included in the plugin', 'top-10' ) . '<br />',
),
array(
'id' => 'left_thumbs',
'name' => esc_html__( 'Left thumbnails', 'top-10' ),
'description' => '<br /><img src="' . esc_url( plugins_url( 'includes/admin/images/tptn-left-thumbs.png', TOP_TEN_PLUGIN_FILE ) ) . '" width="350" /> <br />' . esc_html__( 'Enabling this option will set the post thumbnail to be before text. Disabling this option will not revert any settings.', 'top-10' ),
),
);
/**
* Filter the array containing the types of styles to add your own.
*
* @since 2.5.0
*
* @param string $styles Different styles.
*/
return apply_filters( 'tptn_get_styles', $styles );
}

View File

@@ -0,0 +1,197 @@
<?php
/**
* Help tab.
*
* Functions to generated the help tab on the Settings page.
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin/Help
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Generates the settings help page.
*
* @since 2.5.0
*/
function tptn_settings_help() {
global $tptn_settings_page;
$screen = get_current_screen();
if ( $screen->id !== $tptn_settings_page ) {
return;
}
$screen->set_help_sidebar(
/* translators: 1: Support link. */
'<p>' . sprintf( __( 'For more information or how to get support visit the <a href="%1$s">WebberZone support site</a>.', 'top-10' ), esc_url( 'https://webberzone.com/support/' ) ) . '</p>' .
/* translators: 1: Forum link. */
'<p>' . sprintf( __( 'Support queries should be posted in the <a href="%1$s">WordPress.org support forums</a>.', 'top-10' ), esc_url( 'https://wordpress.org/support/plugin/top-10' ) ) . '</p>' .
'<p>' . sprintf(
/* translators: 1: Github Issues link, 2: Github page. */
__( '<a href="%1$s">Post an issue</a> on <a href="%2$s">GitHub</a> (bug reports only).', 'top-10' ),
esc_url( 'https://github.com/WebberZone/top-10/issues' ),
esc_url( 'https://github.com/WebberZone/top-10' )
) . '</p>'
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-general',
'title' => __( 'General', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides the basic settings for configuring Top 10.', 'top-10' ) . '</p>' .
'<p>' . __( 'Enable the trackers and cache, configure basic tracker settings and uninstall settings.', 'top-10' ) . '</p>',
)
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-counter',
'title' => __( 'Counter/Tracker', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides settings to tweak the display counter and the tracker.', 'top-10' ) . '</p>' .
'<p>' . __( 'Choose where to display the counter and customize the text. Select the type of tracker and which user groups to track.', 'top-10' ) . '</p>',
)
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-list',
'title' => __( 'Posts list', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides settings to tweak the output of the list of popular posts.', 'top-10' ) . '</p>' .
'<p>' . __( 'Set the number of posts, which categories or posts to exclude, customize what to display and specific basic HTML markup used to create the posts.', 'top-10' ) . '</p>',
)
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-thumbnail',
'title' => __( 'Thumbnail', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides settings to tweak the thumbnail that can be displayed for each post in the list.', 'top-10' ) . '</p>' .
'<p>' . __( 'Set the location and size of the thumbnail. Additionally, you can choose additional sources for the thumbnail i.e. a meta field, first image or a default thumbnail when nothing is available.', 'top-10' ) . '</p>',
)
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-styles',
'title' => __( 'Styles', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides options to control the look and feel of the popular posts list.', 'top-10' ) . '</p>' .
'<p>' . __( 'Choose for default set of styles or add your own custom CSS to tweak the display of the posts.', 'top-10' ) . '</p>',
)
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-maintenance',
'title' => __( 'Maintenance', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides options to control the maintenance cron.', 'top-10' ) . '</p>' .
'<p>' . __( 'Choose how often to run maintenance and at what time of the day.', 'top-10' ) . '</p>',
)
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-feed',
'title' => __( 'Feed', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides options to control the custom feeds for the daily and overall popular posts. You can access the custom feed at example.com/feed/popular-posts/ replacing example.com with your blog domain.', 'top-10' ) . '</p>' .
'<p>' . __( 'You can also change the permalink in the settings below. You will need to refresh your permalinks if you change these settings. Alternatively save the settings page twice.', 'top-10' ) . '</p>',
)
);
do_action( 'tptn_settings_help', $screen );
}
/**
* Generates the Tools help page.
*
* @since 2.5.0
*/
function tptn_settings_tools_help() {
global $tptn_settings_tools_help;
$screen = get_current_screen();
if ( $screen->id !== $tptn_settings_tools_help ) {
return;
}
$screen->set_help_sidebar(
/* translators: 1: Support link. */
'<p>' . sprintf( __( 'For more information or how to get support visit the <a href="%1$s">WebberZone support site</a>.', 'top-10' ), esc_url( 'https://webberzone.com/support/' ) ) . '</p>' .
/* translators: 1: Forum link. */
'<p>' . sprintf( __( 'Support queries should be posted in the <a href="%1$s">WordPress.org support forums</a>.', 'top-10' ), esc_url( 'https://wordpress.org/support/plugin/top-10' ) ) . '</p>' .
'<p>' . sprintf(
/* translators: 1: Github Issues link, 2: Github page. */
__( '<a href="%1$s">Post an issue</a> on <a href="%2$s">GitHub</a> (bug reports only).', 'top-10' ),
esc_url( 'https://github.com/WebberZone/top-10/issues' ),
esc_url( 'https://github.com/WebberZone/top-10' )
) . '</p>'
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-general',
'title' => __( 'General', 'top-10' ),
'content' =>
'<p>' . __( 'This screen provides some tools that help maintain certain features of Top 10.', 'top-10' ) . '</p>' .
'<p>' . __( 'Clear the cache, reset the popular posts tables plus some miscellaneous fixes for older versions of Top 10.', 'top-10' ) . '</p>',
)
);
do_action( 'tptn_settings_tools_help', $screen );
}
/**
* Generates the Tools help page.
*
* @since 2.7.0
*/
function tptn_settings_exim_help() {
global $tptn_settings_exim_help;
$screen = get_current_screen();
if ( $screen->id !== $tptn_settings_exim_help ) {
return;
}
$screen->set_help_sidebar(
/* translators: 1: Support link. */
'<p>' . sprintf( __( 'For more information or how to get support visit the <a href="%1$s">WebberZone support site</a>.', 'top-10' ), esc_url( 'https://webberzone.com/support/' ) ) . '</p>' .
/* translators: 1: Forum link. */
'<p>' . sprintf( __( 'Support queries should be posted in the <a href="%1$s">WordPress.org support forums</a>.', 'top-10' ), esc_url( 'https://wordpress.org/support/plugin/top-10' ) ) . '</p>' .
'<p>' . sprintf(
/* translators: 1: Knowledgebase link. */
__( '<a href="%1$s">Top 10 Knowledge base</a>', 'top-10' ),
esc_url( 'https://webberzone.com/support/section/top-10/' )
) . '</p>'
);
$screen->add_help_tab(
array(
'id' => 'tptn-settings-general',
'title' => __( 'General', 'top-10' ),
'content' =>
'<p>' . __( 'This screen allows you to import and export the database tables.', 'top-10' ) . '</p>' .
'<p>' . __( 'Refer to the knowledge base to learn how to use this in detail.', 'top-10' ) . '</p>',
)
);
do_action( 'tptn_settings_tools_help', $screen );
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1 @@
<?php // Silence is golden

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,393 @@
<?php
/**
* Functions to import and export the Top 10 data.
*
* @link https://webberzone.com
* @since 2.7.0
*
* @package Top 10
* @subpackage Admin/Tools/Import_Export
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Render the tools settings page.
*
* @since 2.7.0
*
* @return void
*/
function tptn_exim_page() {
/* Message for successful file import */
if ( isset( $_GET['file_import'] ) && 'success' === $_GET['file_import'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
add_settings_error( 'tptn-notices', '', esc_html__( 'Data has been imported into the table', 'top-10' ), 'updated' );
}
/* Message for successful file import */
if ( isset( $_GET['settings_import'] ) && 'success' === $_GET['settings_import'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
add_settings_error( 'tptn-notices', '', esc_html__( 'Settings have been imported successfully', 'top-10' ), 'updated' );
}
ob_start();
?>
<div class="wrap">
<h1><?php esc_html_e( 'Top 10 - Import/Export tables', 'top-10' ); ?></h1>
<?php settings_errors(); ?>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<form method="post">
<h2 style="padding-left:0px"><?php esc_html_e( 'Export/Import settings', 'top-10' ); ?></h2>
<p class="description">
<?php esc_html_e( 'Export the plugin settings for this site as a .json file. This allows you to easily import the configuration into another site.', 'top-10' ); ?>
</p>
<p><input type="hidden" name="tptn_action" value="export_settings" /></p>
<p>
<?php submit_button( esc_html__( 'Export Settings', 'top-10' ), 'primary', 'tptn_export_settings', false ); ?>
</p>
<?php wp_nonce_field( 'tptn_export_settings_nonce', 'tptn_export_settings_nonce' ); ?>
</form>
<form method="post" enctype="multipart/form-data">
<p class="description">
<?php esc_html_e( 'Import the plugin settings from a .json file. This file can be obtained by exporting the settings on another site using the form above.', 'top-10' ); ?>
</p>
<p>
<input type="file" name="import_settings_file" />
</p>
<p>
<?php submit_button( esc_html__( 'Import Settings', 'top-10' ), 'primary', 'tptn_import_settings', false ); ?>
</p>
<input type="hidden" name="tptn_action" value="import_settings" />
<?php wp_nonce_field( 'tptn_import_settings_nonce', 'tptn_import_settings_nonce' ); ?>
</form>
<form method="post">
<h2 style="padding-left:0px"><?php esc_html_e( 'Export tables', 'top-10' ); ?></h2>
<p class="description">
<?php esc_html_e( 'Click the buttons below to export the overall and the daily tables. The file is downloaded as an CSV file which you should be able to edit in Excel or any other compatible software.', 'top-10' ); ?>
<?php esc_html_e( 'If you are using WordPress Multisite then this will include the counts across all sites as the plugin uses a single table to store counts.', 'top-10' ); ?>
</p>
<p><input type="hidden" name="tptn_action" value="export_tables" /></p>
<p>
<?php submit_button( esc_html__( 'Export overall tables', 'top-10' ), 'primary', 'tptn_export_total', false ); ?>
<?php submit_button( esc_html__( 'Export daily tables', 'top-10' ), 'primary', 'tptn_export_daily', false ); ?>
</p>
<?php wp_nonce_field( 'tptn_export_nonce', 'tptn_export_nonce' ); ?>
</form>
<form method="post" enctype="multipart/form-data">
<h2 style="padding-left:0px"><?php esc_html_e( 'Import tables', 'top-10' ); ?></h2>
<p class="description">
<?php esc_html_e( 'This action will replace the data in your tables, so I suggest that you export the existing data using the buttons above, amend it and then import it. It is important to maintain the export format of the data to avoid corruption.', 'top-10' ); ?>
</p>
<p class="description">
<strong><?php esc_html_e( 'Backup your database before proceeding so you will be able to restore it in case anything goes wrong.', 'top-10' ); ?></strong>
</p>
<h4 style="padding-left:0px"><?php esc_html_e( 'Import Overall Table', 'top-10' ); ?></h4>
<p>
<input type="file" name="import_file" />
</p>
<p>
<?php submit_button( esc_html__( 'Import Overall CSV', 'top-10' ), 'primary', 'tptn_import_total', false ); ?>
</p>
<h4 style="padding-left:0px"><?php esc_html_e( 'Import Daily Table', 'top-10' ); ?></h4>
<p>
<input type="file" name="import_file_daily" />
</p>
<p>
<?php submit_button( esc_html__( 'Import Daily CSV', 'top-10' ), 'primary', 'tptn_import_daily', false ); ?>
</p>
<input type="hidden" name="tptn_action" value="import_tables" />
<?php wp_nonce_field( 'tptn_import_nonce', 'tptn_import_nonce' ); ?>
</form>
</div><!-- /#post-body-content -->
<div id="postbox-container-1" class="postbox-container">
<div id="side-sortables" class="meta-box-sortables ui-sortable">
<?php include_once 'sidebar.php'; ?>
</div><!-- /#side-sortables -->
</div><!-- /#postbox-container-1 -->
</div><!-- /#post-body -->
<br class="clear" />
</div><!-- /#poststuff -->
</div><!-- /.wrap -->
<?php
echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Process a settings export that generates a .csv file of the Top 10 table.
*
* @since 2.7.0
*/
function tptn_export_tables() {
global $wpdb;
if ( empty( $_POST['tptn_action'] ) || 'export_tables' !== $_POST['tptn_action'] ) {
return;
}
if ( ! wp_verify_nonce( sanitize_key( $_POST['tptn_export_nonce'] ), 'tptn_export_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( isset( $_POST['tptn_export_total'] ) ) {
$daily = false;
} elseif ( isset( $_POST['tptn_export_daily'] ) ) {
$daily = true;
} else {
return;
}
$table_name = $wpdb->base_prefix . 'top_ten';
if ( $daily ) {
$table_name .= '_daily';
}
$filename = 'top-ten' . ( $daily ? '-daily' : '' ) . '-table-' . current_time( 'Y_m_d_Hi' ) . '.csv';
$header_row = array(
esc_html__( 'Post ID', 'top-10' ),
esc_html__( 'Visits', 'top-10' ),
);
if ( $daily ) {
$header_row[] = esc_html__( 'Date', 'top-10' );
}
$header_row[] = esc_html__( 'Blog ID', 'top-10' );
$data_rows = array();
$sql = 'SELECT * FROM ' . $table_name;
$results = $wpdb->get_results( $sql, 'ARRAY_A' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
foreach ( $results as $result ) {
$row = array(
$result['postnumber'],
$result['cntaccess'],
);
if ( $daily ) {
$row[] = $result['dp_date'];
}
$row[] = $result['blog_id'];
$data_rows[] = $row;
}
ignore_user_abort( true );
$fh = fopen( 'php://output', 'w' );
fprintf( $fh, chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF ) );
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( "Content-Disposition: attachment; filename={$filename}" );
header( 'Expires: 0' );
fputcsv( $fh, $header_row );
foreach ( $data_rows as $data_row ) {
fputcsv( $fh, $data_row );
}
fclose( $fh ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
exit;
}
add_action( 'admin_init', 'tptn_export_tables' );
/**
* Process a .csv file to import the table into the database.
*
* @since 2.7.0
*/
function tptn_import_tables() {
global $wpdb;
if ( empty( $_POST['tptn_action'] ) || 'import_tables' !== $_POST['tptn_action'] ) {
return;
}
if ( ! wp_verify_nonce( sanitize_key( $_POST['tptn_import_nonce'] ), 'tptn_import_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
if ( isset( $_POST['tptn_import_total'] ) ) {
$daily = false;
} elseif ( isset( $_POST['tptn_import_daily'] ) ) {
$daily = true;
} else {
return;
}
$table_name = $wpdb->base_prefix . 'top_ten';
$filename = 'import_file';
if ( $daily ) {
$table_name .= '_daily';
$filename .= '_daily';
}
$extension = isset( $_FILES[ $filename ]['name'] ) ? end( explode( '.', sanitize_file_name( wp_unslash( $_FILES[ $filename ]['name'] ) ) ) ) : '';
if ( 'csv' !== $extension ) {
wp_die( esc_html__( 'Please upload a valid .csv file', 'top-10' ) );
}
$import_file = isset( $_FILES[ $filename ]['tmp_name'] ) ? ( wp_unslash( $_FILES[ $filename ]['tmp_name'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( empty( $import_file ) ) {
wp_die( esc_html__( 'Please upload a file to import', 'top-10' ) );
}
// Truncate the table before import.
tptn_trunc_count( $daily );
// Open uploaded CSV file with read-only mode.
$csv_file = fopen( $import_file, 'r' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen
// Skip first line.
fgetcsv( $csv_file );
while ( ( $line = fgetcsv( $csv_file, 100, ',' ) ) !== false ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
if ( $daily ) {
$dp_date = str_replace( '/', '-', $line[2] );
$dp_date = gmdate( 'Y-m-d H', strtotime( $dp_date ) );
$wpdb->query( $wpdb->prepare( "INSERT INTO {$table_name} (postnumber, cntaccess, dp_date, blog_id) VALUES( %d, %d, %s, %d ) ", $line[0], $line[1], $dp_date, $line[3] ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
} else {
$wpdb->query( $wpdb->prepare( "INSERT INTO {$table_name} (postnumber, cntaccess, blog_id) VALUES( %d, %d, %d ) ", $line[0], $line[1], $line[2] ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
}
// Close file.
fclose( $csv_file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose
wp_safe_redirect(
add_query_arg(
array(
'page' => 'tptn_exim_page',
'file_import' => 'success',
),
admin_url( 'admin.php' )
)
);
exit;
}
add_action( 'admin_init', 'tptn_import_tables', 9 );
/**
* Process a settings export that generates a .json file of the Top 10 settings
*
* @since 2.7.0
*/
function tptn_process_settings_export() {
if ( empty( $_POST['tptn_action'] ) || 'export_settings' !== $_POST['tptn_action'] ) {
return;
}
if ( ! wp_verify_nonce( sanitize_key( $_POST['tptn_export_settings_nonce'] ), 'tptn_export_settings_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$settings = get_option( 'tptn_settings' );
ignore_user_abort( true );
nocache_headers();
header( 'Content-Type: application/json; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=tptn-settings-export-' . gmdate( 'm-d-Y' ) . '.json' );
header( 'Expires: 0' );
echo wp_json_encode( $settings );
exit;
}
add_action( 'admin_init', 'tptn_process_settings_export' );
/**
* Process a settings import from a json file
*
* @since 2.7.0
*/
function tptn_process_settings_import() {
if ( empty( $_POST['tptn_action'] ) || 'import_settings' !== $_POST['tptn_action'] ) {
return;
}
if ( ! wp_verify_nonce( sanitize_key( $_POST['tptn_import_settings_nonce'] ), 'tptn_import_settings_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$filename = 'import_settings_file';
$extension = isset( $_FILES[ $filename ]['name'] ) ? end( explode( '.', sanitize_file_name( wp_unslash( $_FILES[ $filename ]['name'] ) ) ) ) : '';
if ( 'json' !== $extension ) {
wp_die( esc_html__( 'Please upload a valid .json file', 'top-10' ) );
}
$import_file = isset( $_FILES[ $filename ]['tmp_name'] ) ? ( wp_unslash( $_FILES[ $filename ]['tmp_name'] ) ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( empty( $import_file ) ) {
wp_die( esc_html__( 'Please upload a file to import', 'top-10' ) );
}
// Retrieve the settings from the file and convert the json object to an array.
$settings = (array) json_decode( file_get_contents( $import_file ), true ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
update_option( 'tptn_settings', $settings );
wp_safe_redirect(
add_query_arg(
array(
'page' => 'tptn_exim_page',
'settings_import' => 'success',
),
admin_url( 'admin.php' )
)
);
exit;
}
add_action( 'admin_init', 'tptn_process_settings_import', 9 );

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,169 @@
// Function to clear the cache.
function clearCache() {
/**** since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php ****/
jQuery.post(ajaxurl, {
action: 'tptn_clear_cache'
}, function (response, textStatus, jqXHR) {
alert(response.message);
}, 'json');
}
jQuery(document).ready(function($) {
// Prompt the user when they leave the page without saving the form.
formmodified=0;
function confirmFormChange() {
formmodified=1;
}
function confirmExit() {
if ( formmodified == 1 ) {
return true;
}
}
function formNotModified() {
formmodified = 0;
}
$('form *').change( confirmFormChange );
window.onbeforeunload = confirmExit;
$( "input[name='submit']" ).click(formNotModified);
$( "input[id='search-submit']" ).click(formNotModified);
$( "input[id='doaction']" ).click(formNotModified);
$( "input[id='doaction2']" ).click(formNotModified);
$( "input[name='filter_action']" ).click(formNotModified);
$( function() {
$( "#post-body-content" ).tabs({
create: function( event, ui ) {
$( ui.tab.find("a") ).addClass( "nav-tab-active" );
},
activate: function( event, ui ) {
$( ui.oldTab.find("a") ).removeClass( "nav-tab-active" );
$( ui.newTab.find("a") ).addClass( "nav-tab-active" );
}
});
});
// Datepicker.
$( function() {
var dateFormat = 'dd M yy',
from = $( "#datepicker-from" )
.datepicker({
changeMonth: true,
maxDate: 0,
dateFormat: dateFormat
})
.on( "change", function() {
to.datepicker( "option", "minDate", getDate( this ) );
}),
to = $( "#datepicker-to" )
.datepicker({
changeMonth: true,
maxDate: 0,
dateFormat: dateFormat
})
.on( "change", function() {
from.datepicker( "option", "maxDate", getDate( this ) );
});
function getDate( element ) {
var date;
try {
date = $.datepicker.parseDate( dateFormat, element.value );
} catch( error ) {
date = null;
}
return date;
}
} );
// Initialise CodeMirror.
$( ".codemirror_html" ).each( function( index, element ) {
if( $( element ).length && typeof wp.codeEditor === 'object' ) {
var editorSettings = wp.codeEditor.defaultSettings ? _.clone( wp.codeEditor.defaultSettings ) : {};
editorSettings.codemirror = _.extend(
{},
editorSettings.codemirror,
{
}
);
var editor = wp.codeEditor.initialize( $( element ), editorSettings );
editor.codemirror.on( 'change', confirmFormChange );
}
});
$( ".codemirror_js" ).each( function( index, element ) {
if( $( element ).length && typeof wp.codeEditor === 'object' ) {
var editorSettings = wp.codeEditor.defaultSettings ? _.clone( wp.codeEditor.defaultSettings ) : {};
editorSettings.codemirror = _.extend(
{},
editorSettings.codemirror,
{
mode: 'javascript',
}
);
var editor = wp.codeEditor.initialize( $( element ), editorSettings );
editor.codemirror.on( 'change', confirmFormChange );
}
});
$( ".codemirror_css" ).each( function( index, element ) {
if( $( element ).length && typeof wp.codeEditor === 'object' ) {
var editorSettings = wp.codeEditor.defaultSettings ? _.clone( wp.codeEditor.defaultSettings ) : {};
editorSettings.codemirror = _.extend(
{},
editorSettings.codemirror,
{
mode: 'css',
}
);
var editor = wp.codeEditor.initialize( $( element ), editorSettings );
editor.codemirror.on( 'change', confirmFormChange );
}
});
// Editable table code.
$('.live_edit').click(function(){
$(this).addClass('live_edit_mode');
$(this).removeClass("live_edit_mode_success");
$(this).removeClass("live_edit_mode_error");
});
$(".live_edit").on('focusout keypress',function(e){
if (e.type !== "focusout" && e.which !== 13) {
return;
}
var $element = $( this );
var post_id = $element.attr( 'data-wp-post-id' );
var count = $element.attr( 'data-wp-count' );
var value = $element.text();
$element.removeClass("live_edit_mode");
$.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
action: 'tptn_edit_count_ajax',
post_id: post_id,
total_count: value,
total_count_original: count
},
success: function( response ) {
if ( response === false ) {
$element.addClass("live_edit_mode_error");
$element.html(count);
} else if ( response > 0 ) {
$element.addClass("live_edit_mode_success");
}
},
});
});
});

View File

@@ -0,0 +1 @@
function clearCache(){jQuery.post(ajaxurl,{action:"tptn_clear_cache"},(function(response,textStatus,jqXHR){alert(response.message)}),"json")}jQuery(document).ready((function($){function confirmFormChange(){formmodified=1}function confirmExit(){if(1==formmodified)return!0}function formNotModified(){formmodified=0}formmodified=0,$("form *").change(confirmFormChange),window.onbeforeunload=confirmExit,$("input[name='submit']").click(formNotModified),$("input[id='search-submit']").click(formNotModified),$("input[id='doaction']").click(formNotModified),$("input[id='doaction2']").click(formNotModified),$("input[name='filter_action']").click(formNotModified),$((function(){$("#post-body-content").tabs({create:function(event,ui){$(ui.tab.find("a")).addClass("nav-tab-active")},activate:function(event,ui){$(ui.oldTab.find("a")).removeClass("nav-tab-active"),$(ui.newTab.find("a")).addClass("nav-tab-active")}})})),$((function(){var dateFormat="dd M yy",from=$("#datepicker-from").datepicker({changeMonth:!0,maxDate:0,dateFormat:"dd M yy"}).on("change",(function(){to.datepicker("option","minDate",getDate(this))})),to=$("#datepicker-to").datepicker({changeMonth:!0,maxDate:0,dateFormat:"dd M yy"}).on("change",(function(){from.datepicker("option","maxDate",getDate(this))}));function getDate(element){var date;try{date=$.datepicker.parseDate("dd M yy",element.value)}catch(error){date=null}return date}})),$(".codemirror_html").each((function(index,element){if($(element).length&&"object"==typeof wp.codeEditor){var editorSettings=wp.codeEditor.defaultSettings?_.clone(wp.codeEditor.defaultSettings):{},editor;editorSettings.codemirror=_.extend({},editorSettings.codemirror,{}),wp.codeEditor.initialize($(element),editorSettings).codemirror.on("change",confirmFormChange)}})),$(".codemirror_js").each((function(index,element){if($(element).length&&"object"==typeof wp.codeEditor){var editorSettings=wp.codeEditor.defaultSettings?_.clone(wp.codeEditor.defaultSettings):{},editor;editorSettings.codemirror=_.extend({},editorSettings.codemirror,{mode:"javascript"}),wp.codeEditor.initialize($(element),editorSettings).codemirror.on("change",confirmFormChange)}})),$(".codemirror_css").each((function(index,element){if($(element).length&&"object"==typeof wp.codeEditor){var editorSettings=wp.codeEditor.defaultSettings?_.clone(wp.codeEditor.defaultSettings):{},editor;editorSettings.codemirror=_.extend({},editorSettings.codemirror,{mode:"css"}),wp.codeEditor.initialize($(element),editorSettings).codemirror.on("change",confirmFormChange)}})),$(".live_edit").click((function(){$(this).addClass("live_edit_mode"),$(this).removeClass("live_edit_mode_success"),$(this).removeClass("live_edit_mode_error")})),$(".live_edit").on("focusout keypress",(function(e){if("focusout"===e.type||13===e.which){var $element=$(this),post_id=$element.attr("data-wp-post-id"),count=$element.attr("data-wp-count"),value=$element.text();$element.removeClass("live_edit_mode"),$.ajax({type:"POST",dataType:"json",url:ajaxurl,data:{action:"tptn_edit_count_ajax",post_id:post_id,total_count:value,total_count_original:count},success:function(response){!1===response?($element.addClass("live_edit_mode_error"),$element.html(count)):response>0&&$element.addClass("live_edit_mode_success")}})}}))}));

View File

@@ -0,0 +1,115 @@
// Function to clear the cache.
function updateChart() {
jQuery.post(ajaxurl, {
action: 'tptn_chart_data',
security: tptn_chart_data.security,
from_date: jQuery('#datepicker-from').val(),
to_date: jQuery('#datepicker-to').val()
}, function (data) {
var date = [];
var visits = [];
for(var i in data) {
date.push(data[i].date);
visits.push(data[i].visits);
}
console.log(date);
console.log(visits);
window.top10chart.data.labels = date;
window.top10chart.data.datasets.forEach((dataset) => {
dataset.data = visits;
});
window.top10chart.update();
}, 'json');
}
jQuery(document).ready(function($) {
$.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
action: 'tptn_chart_data',
security: tptn_chart_data.security,
from_date: $('#datepicker-from').val(),
to_date: $('#datepicker-to').val()
},
success: function(data) {
var date = [];
var visits = [];
for(var i in data) {
date.push(data[i].date);
visits.push(data[i].visits);
}
var ctx = $("#visits");
var config = {
type: 'bar',
data: {
labels: date,
datasets : [
{
label: tptn_chart_data.datasetlabel,
backgroundColor: '#70c4e1',
borderColor: '#70c4e1',
hoverBackgroundColor: '#ffbf00',
hoverBorderColor: '#ffbf00',
data: visits
}
]
},
plugins: [ChartDataLabels],
options: {
plugins: {
title: {
text: tptn_chart_data.charttitle,
display: true
},
legend: {
display: false,
position: 'bottom'
},
datalabels: {
color: '#000000',
anchor: 'end',
align: 'top'
}
},
scales: {
x: {
type: 'time',
time: {
tooltipFormat: 'll',
unit: 'day',
displayFormats: {
day: 'DD MMM YY'
}
},
scaleLabel: {
display: false,
labelString: 'Date'
}
},
y: {
grace: '5%',
suggestedMin: 0,
scaleLabel: {
display: true,
labelString: tptn_chart_data.datasetlabel
}
}
},
}
};
window.top10chart = new Chart(ctx, config);
},
error: function(data) {
console.log(data);
}
});
});

View File

@@ -0,0 +1 @@
function updateChart(){jQuery.post(ajaxurl,{action:"tptn_chart_data",security:tptn_chart_data.security,from_date:jQuery("#datepicker-from").val(),to_date:jQuery("#datepicker-to").val()},(function(data){var date=[],visits=[];for(var i in data)date.push(data[i].date),visits.push(data[i].visits);console.log(date),console.log(visits),window.top10chart.data.labels=date,window.top10chart.data.datasets.forEach(dataset=>{dataset.data=visits}),window.top10chart.update()}),"json")}jQuery(document).ready((function($){$.ajax({type:"POST",dataType:"json",url:ajaxurl,data:{action:"tptn_chart_data",security:tptn_chart_data.security,from_date:$("#datepicker-from").val(),to_date:$("#datepicker-to").val()},success:function(data){var date=[],visits=[];for(var i in data)date.push(data[i].date),visits.push(data[i].visits);var ctx=$("#visits"),config={type:"bar",data:{labels:date,datasets:[{label:tptn_chart_data.datasetlabel,backgroundColor:"#70c4e1",borderColor:"#70c4e1",hoverBackgroundColor:"#ffbf00",hoverBorderColor:"#ffbf00",data:visits}]},plugins:[ChartDataLabels],options:{plugins:{title:{text:tptn_chart_data.charttitle,display:!0},legend:{display:!1,position:"bottom"},datalabels:{color:"#000000",anchor:"end",align:"top"}},scales:{x:{type:"time",time:{tooltipFormat:"ll",unit:"day",displayFormats:{day:"DD MMM YY"}},scaleLabel:{display:!1,labelString:"Date"}},y:{grace:"5%",suggestedMin:0,scaleLabel:{display:!0,labelString:tptn_chart_data.datasetlabel}}}}};window.top10chart=new Chart(ctx,config)},error:function(data){console.log(data)}})}));

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
/*!
* chartjs-adapter-moment v1.0.0
* https://www.chartjs.org
* (c) 2021 chartjs-adapter-moment Contributors
* Released under the MIT license
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("moment"),require("chart.js")):"function"==typeof define&&define.amd?define(["moment","chart.js"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).moment,e.Chart)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f=n(e);const a={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};t._adapters._date.override("function"==typeof f.default?{_id:"moment",formats:function(){return a},parse:function(e,t){return"string"==typeof e&&"string"==typeof t?e=f.default(e,t):e instanceof f.default||(e=f.default(e)),e.isValid()?e.valueOf():null},format:function(e,t){return f.default(e).format(t)},add:function(e,t,n){return f.default(e).add(t,n).valueOf()},diff:function(e,t,n){return f.default(e).diff(f.default(t),n)},startOf:function(e,t,n){return e=f.default(e),"isoWeek"===t?(n=Math.trunc(Math.min(Math.max(0,n),6)),e.isoWeekday(n).startOf("day").valueOf()):e.startOf(t).valueOf()},endOf:function(e,t){return f.default(e).endOf(t).valueOf()}}:{})}));
//# sourceMappingURL=chartjs-adapter-moment.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
<?php // Silence is golden

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,110 @@
jQuery(document).ready(function($) {
// Function to add auto suggest.
$.fn.tptnTagsSuggest = function( options ) {
var cache;
var last;
var $element = $( this );
options = options || {};
var taxonomy = options.taxonomy || $element.attr( 'data-wp-taxonomy' ) || 'category';
delete( options.taxonomy );
function split( val ) {
return val.split( /,(?=(?:(?:[^"]*"){2})*[^"]*$)/ ); // Split typical CSV format, with commas and double quotes.
}
function extractLast( term ) {
return split( term ).pop();
}
options = $.extend({
minLength: 2,
position: {
my: 'left top+2',
at: 'left bottom',
collision: 'none'
},
source: function( request, response ) {
var term;
if ( last === request.term ) {
response( cache );
return;
}
term = extractLast( request.term );
if ( last === request.term ) {
response( cache );
return;
}
$.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
action: 'tptn_tag_search',
tax: taxonomy,
q: term
},
}).done( function( data ) {
cache = data;
response( data );
});
last = request.term;
},
search: function() {
// Custom minLength.
var term = extractLast( this.value );
if ( term.length < 2 ) {
return false;
}
},
focus: function( event, ui ) {
// Prevent value inserted on focus.
event.preventDefault();
},
select: function( event, ui ) {
var terms = split( this.value );
var val = ui.item.value;
if ( val.indexOf(',') !== -1 ) {
val = '"' + val + '"'
}
// Remove the last user input.
terms.pop();
// Add the selected item.
terms.push( val );
// Add placeholder to get the comma-and-space at the end.
terms.push( "" );
this.value = terms.join( ", " );
return false;
}
}, options );
$element.on( "keydown", function( event ) {
// Don't navigate away from the field on tab when selecting an item.
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( 'instance' ).menu.active ) {
event.preventDefault();
}
})
.autocomplete( options );
};
$( '.category_autocomplete' ).each( function ( i, element ) {
$( element ).tptnTagsSuggest();
});
$('.widget-liquid-right, #customize-controls').on( 'click', '.category_autocomplete', function() {
$( '.category_autocomplete' ).tptnTagsSuggest();
});
});

View File

@@ -0,0 +1 @@
jQuery(document).ready((function($){$.fn.tptnTagsSuggest=function(options){var cache,last,$element=$(this),taxonomy=(options=options||{}).taxonomy||$element.attr("data-wp-taxonomy")||"category";function split(val){return val.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/)}function extractLast(term){return split(term).pop()}delete options.taxonomy,options=$.extend({minLength:2,position:{my:"left top+2",at:"left bottom",collision:"none"},source:function(request,response){var term;last!==request.term?(term=extractLast(request.term),last!==request.term?($.ajax({type:"POST",dataType:"json",url:ajaxurl,data:{action:"tptn_tag_search",tax:taxonomy,q:term}}).done((function(data){cache=data,response(data)})),last=request.term):response(cache)):response(cache)},search:function(){var term;if(extractLast(this.value).length<2)return!1},focus:function(event,ui){event.preventDefault()},select:function(event,ui){var terms=split(this.value),val=ui.item.value;return-1!==val.indexOf(",")&&(val='"'+val+'"'),terms.pop(),terms.push(val),terms.push(""),this.value=terms.join(", "),!1}},options),$element.on("keydown",(function(event){event.keyCode===$.ui.keyCode.TAB&&$(this).autocomplete("instance").menu.active&&event.preventDefault()})).autocomplete(options)},$(".category_autocomplete").each((function(i,element){$(element).tptnTagsSuggest()})),$(".widget-liquid-right, #customize-controls").on("click",".category_autocomplete",(function(){$(".category_autocomplete").tptnTagsSuggest()}))}));

View File

@@ -0,0 +1,325 @@
<?php
/**
* Register settings.
*
* Functions to register, read, write and update settings.
* Portions of this code have been inspired by Easy Digital Downloads, WordPress Settings Sandbox, etc.
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin/Register_Settings
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Get an option
*
* Looks to see if the specified setting exists, returns default if not
*
* @since 2.5.0
*
* @param string $key Key of the option to fetch.
* @param mixed $default Default value to fetch if option is missing.
* @return mixed
*/
function tptn_get_option( $key = '', $default = null ) {
global $tptn_settings;
if ( empty( $tptn_settings ) ) {
$tptn_settings = tptn_get_settings();
}
if ( is_null( $default ) ) {
$default = tptn_get_default_option( $key );
}
$value = isset( $tptn_settings[ $key ] ) ? $tptn_settings[ $key ] : $default;
/**
* Filter the value for the option being fetched.
*
* @since 2.5.0
*
* @param mixed $value Value of the option
* @param mixed $key Name of the option
* @param mixed $default Default value
*/
$value = apply_filters( 'tptn_get_option', $value, $key, $default );
/**
* Key specific filter for the value of the option being fetched.
*
* @since 2.5.0
*
* @param mixed $value Value of the option
* @param mixed $key Name of the option
* @param mixed $default Default value
*/
return apply_filters( 'tptn_get_option_' . $key, $value, $key, $default );
}
/**
* Update an option
*
* Updates an tptn setting value in both the db and the global variable.
* Warning: Passing in a null value will remove
* the key from the tptn_options array.
*
* @since 2.5.0
*
* @param string $key The Key to update.
* @param string|bool|int $value The value to set the key to.
* @return boolean True if updated, false if not.
*/
function tptn_update_option( $key = '', $value = null ) {
// If no key, exit.
if ( empty( $key ) ) {
return false;
}
// If null value, delete.
if ( is_null( $value ) ) {
$remove_option = tptn_delete_option( $key );
return $remove_option;
}
// First let's grab the current settings.
$options = get_option( 'tptn_settings' );
/**
* Filters the value before it is updated
*
* @since 2.5.0
*
* @param string|bool|int $value The value to set the key to
* @param string $key The Key to update
*/
$value = apply_filters( 'tptn_update_option', $value, $key );
// Next let's try to update the value.
$options[ $key ] = $value;
$did_update = update_option( 'tptn_settings', $options );
// If it updated, let's update the global variable.
if ( $did_update ) {
global $tptn_settings;
$tptn_settings[ $key ] = $value;
}
return $did_update;
}
/**
* Remove an option
*
* Removes an tptn setting value in both the db and the global variable.
*
* @since 2.5.0
*
* @param string $key The Key to update.
* @return boolean True if updated, false if not.
*/
function tptn_delete_option( $key = '' ) {
// If no key, exit.
if ( empty( $key ) ) {
return false;
}
// First let's grab the current settings.
$options = get_option( 'tptn_settings' );
// Next let's try to update the value.
if ( isset( $options[ $key ] ) ) {
unset( $options[ $key ] );
}
$did_update = update_option( 'tptn_settings', $options );
// If it updated, let's update the global variable.
if ( $did_update ) {
global $tptn_settings;
$tptn_settings = $options;
}
return $did_update;
}
/**
* Register settings function
*
* @since 2.5.0
*
* @return void
*/
function tptn_register_settings() {
if ( false === get_option( 'tptn_settings' ) ) {
add_option( 'tptn_settings', tptn_settings_defaults() );
}
foreach ( tptn_get_registered_settings() as $section => $settings ) {
add_settings_section(
'tptn_settings_' . $section, // ID used to identify this section and with which to register options, e.g. tptn_settings_general.
__return_null(), // No title, we will handle this via a separate function.
'__return_false', // No callback function needed. We'll process this separately.
'tptn_settings_' . $section // Page on which these options will be added.
);
foreach ( $settings as $setting ) {
$args = wp_parse_args(
$setting,
array(
'section' => $section,
'id' => null,
'name' => '',
'desc' => '',
'type' => null,
'options' => '',
'max' => null,
'min' => null,
'step' => null,
'size' => null,
'field_class' => '',
'field_attributes' => '',
'placeholder' => '',
)
);
add_settings_field(
'tptn_settings[' . $args['id'] . ']', // ID of the settings field. We save it within the tptn_settings array.
$args['name'], // Label of the setting.
function_exists( 'tptn_' . $args['type'] . '_callback' ) ? 'tptn_' . $args['type'] . '_callback' : 'tptn_missing_callback', // Function to handle the setting.
'tptn_settings_' . $section, // Page to display the setting. In our case it is the section as defined above.
'tptn_settings_' . $section, // Name of the section.
$args
);
}
}
// Register the settings into the options table.
register_setting( 'tptn_settings', 'tptn_settings', 'tptn_settings_sanitize' );
}
add_action( 'admin_init', 'tptn_register_settings' );
/**
* Flattens tptn_get_registered_settings() into $setting[id] => $setting[type] format.
*
* @since 2.5.0
*
* @return array Default settings
*/
function tptn_get_registered_settings_types() {
$options = array();
// Populate some default values.
foreach ( tptn_get_registered_settings() as $tab => $settings ) {
foreach ( $settings as $option ) {
$options[ $option['id'] ] = $option['type'];
}
}
/**
* Filters the settings array.
*
* @since 2.5.0
*
* @param array $options Default settings.
*/
return apply_filters( 'tptn_get_settings_types', $options );
}
/**
* Default settings.
*
* @since 2.5.0
*
* @return array Default settings
*/
function tptn_settings_defaults() {
$options = array();
// Populate some default values.
foreach ( tptn_get_registered_settings() as $tab => $settings ) {
foreach ( $settings as $option ) {
// When checkbox is set to true, set this to 1.
if ( 'checkbox' === $option['type'] && ! empty( $option['options'] ) ) {
$options[ $option['id'] ] = 1;
} else {
$options[ $option['id'] ] = 0;
}
// If an option is set.
if ( in_array( $option['type'], array( 'textarea', 'text', 'csv', 'numbercsv', 'posttypes', 'number', 'css', 'taxonomies' ), true ) && isset( $option['options'] ) ) {
$options[ $option['id'] ] = $option['options'];
}
if ( in_array( $option['type'], array( 'multicheck', 'radio', 'select', 'radiodesc', 'thumbsizes' ), true ) && isset( $option['default'] ) ) {
$options[ $option['id'] ] = $option['default'];
}
}
}
$upgraded_settings = tptn_upgrade_settings();
if ( false !== $upgraded_settings ) {
$options = array_merge( $options, $upgraded_settings );
}
/**
* Filters the default settings array.
*
* @since 2.5.0
*
* @param array $options Default settings.
*/
return apply_filters( 'tptn_settings_defaults', $options );
}
/**
* Get the default option for a specific key
*
* @since 2.5.0
*
* @param string $key Key of the option to fetch.
* @return mixed
*/
function tptn_get_default_option( $key = '' ) {
$default_settings = tptn_settings_defaults();
if ( array_key_exists( $key, $default_settings ) ) {
return $default_settings[ $key ];
} else {
return false;
}
}
/**
* Reset settings.
*
* @since 2.5.0
*
* @return void
*/
function tptn_settings_reset() {
delete_option( 'tptn_settings' );
}

View File

@@ -0,0 +1,379 @@
<?php
/**
* Save settings.
*
* Functions to register, read, write and update settings.
* Portions of this code have been inspired by Easy Digital Downloads, WordPress Settings Sandbox, etc.
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin/Save_Settings
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Sanitize the form data being submitted.
*
* @since 2.5.0
* @param array $input Input unclean array.
* @return array Sanitized array
*/
function tptn_settings_sanitize( $input = array() ) {
// First, we read the options collection.
global $tptn_settings;
// This should be set if a form is submitted, so let's save it in the $referrer variable.
if ( empty( $_POST['_wp_http_referer'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
return $input;
}
parse_str( sanitize_text_field( wp_unslash( $_POST['_wp_http_referer'] ) ), $referrer ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
// Get the various settings we've registered.
$settings = tptn_get_registered_settings();
$settings_types = tptn_get_registered_settings_types();
// Check if we need to set to defaults.
$reset = isset( $_POST['settings_reset'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( $reset ) {
tptn_settings_reset();
$tptn_settings = tptn_get_settings();
add_settings_error( 'tptn-notices', '', __( 'Settings have been reset to their default values. Reload this page to view the updated settings', 'top-10' ), 'error' );
// Flush rewrite rules.
flush_rewrite_rules();
return $tptn_settings;
}
// Get the tab. This is also our settings' section.
$tab = isset( $referrer['tab'] ) ? $referrer['tab'] : 'general';
$input = $input ? $input : array();
/**
* Filter the settings for the tab. e.g. tptn_settings_general_sanitize.
*
* @since 2.5.0
* @param array $input Input unclean array
*/
$input = apply_filters( 'tptn_settings_' . $tab . '_sanitize', $input );
// Create out output array by merging the existing settings with the ones submitted.
$output = array_merge( $tptn_settings, $input );
// Loop through each setting being saved and pass it through a sanitization filter.
foreach ( $settings_types as $key => $type ) {
/**
* Skip settings that are not really settings.
*
* @since 2.5.0
* @param array $non_setting_types Array of types which are not settings.
*/
$non_setting_types = apply_filters( 'tptn_non_setting_types', array( 'header', 'descriptive_text' ) );
if ( in_array( $type, $non_setting_types, true ) ) {
continue;
}
if ( array_key_exists( $key, $output ) ) {
/**
* Field type filter.
*
* @since 2.5.0
* @param array $output[$key] Setting value.
* @param array $key Setting key.
*/
$output[ $key ] = apply_filters( 'tptn_settings_sanitize_' . $type, $output[ $key ], $key );
}
/**
* Field type filter for a specific key.
*
* @since 2.5.0
* @param array $output[$key] Setting value.
* @param array $key Setting key.
*/
$output[ $key ] = apply_filters( 'tptn_settings_sanitize' . $key, $output[ $key ], $key );
// Delete any key that is not present when we submit the input array.
if ( ! isset( $input[ $key ] ) ) {
unset( $output[ $key ] );
}
// Delete any settings that are no longer part of our registered settings.
if ( array_key_exists( $key, $output ) && ! array_key_exists( $key, $settings_types ) ) {
unset( $output[ $key ] );
}
}
// Flush rewrite rules.
flush_rewrite_rules();
add_settings_error( 'tptn-notices', '', __( 'Settings updated.', 'top-10' ), 'updated' );
/**
* Filter the settings array before it is returned.
*
* @since 2.5.0
* @param array $output Settings array.
* @param array $input Input settings array.
*/
return apply_filters( 'tptn_settings_sanitize', $output, $input );
}
/**
* Sanitize text fields
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_text_field( $value ) {
return tptn_sanitize_textarea_field( $value );
}
add_filter( 'tptn_settings_sanitize_text', 'tptn_sanitize_text_field' );
/**
* Sanitize number fields
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_number_field( $value ) {
return filter_var( $value, FILTER_SANITIZE_NUMBER_INT );
}
add_filter( 'tptn_settings_sanitize_number', 'tptn_sanitize_number_field' );
/**
* Sanitize CSV fields
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_csv_field( $value ) {
return implode( ',', array_map( 'trim', explode( ',', sanitize_text_field( wp_unslash( $value ) ) ) ) );
}
add_filter( 'tptn_settings_sanitize_csv', 'tptn_sanitize_csv_field' );
/**
* Sanitize CSV fields which hold numbers e.g. IDs
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_numbercsv_field( $value ) {
return implode( ',', array_filter( array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $value ) ) ) ) ) );
}
add_filter( 'tptn_settings_sanitize_numbercsv', 'tptn_sanitize_numbercsv_field' );
/**
* Sanitize textarea fields
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_textarea_field( $value ) {
global $allowedposttags;
// We need more tags to allow for script and style.
$moretags = array(
'script' => array(
'type' => true,
'src' => true,
'async' => true,
'defer' => true,
'charset' => true,
'lang' => true,
),
'style' => array(
'type' => true,
'media' => true,
'scoped' => true,
'lang' => true,
),
'link' => array(
'rel' => true,
'type' => true,
'href' => true,
'media' => true,
'sizes' => true,
'hreflang' => true,
),
);
$allowedtags = array_merge( $allowedposttags, $moretags );
/**
* Filter allowed tags allowed when sanitizing text and textarea fields.
*
* @since 2.5.0
*
* @param array $allowedtags Allowed tags array.
* @param array $value The field value.
*/
$allowedtags = apply_filters( 'tptn_sanitize_allowed_tags', $allowedtags, $value );
return wp_kses( wp_unslash( $value ), $allowedtags );
}
add_filter( 'tptn_settings_sanitize_textarea', 'tptn_sanitize_textarea_field' );
/**
* Sanitize checkbox fields
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string|int $value Sanitized value
*/
function tptn_sanitize_checkbox_field( $value ) {
$value = ( -1 === (int) $value ) ? 0 : 1;
return $value;
}
add_filter( 'tptn_settings_sanitize_checkbox', 'tptn_sanitize_checkbox_field' );
/**
* Sanitize post_types fields
*
* @since 2.5.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_posttypes_field( $value ) {
$post_types = is_array( $value ) ? array_map( 'sanitize_text_field', wp_unslash( $value ) ) : array( 'post' );
return implode( ',', $post_types );
}
add_filter( 'tptn_settings_sanitize_posttypes', 'tptn_sanitize_posttypes_field' );
/**
* Sanitize taxonomies fields
*
* @since 3.0.0
*
* @param array $value The field value.
* @return string $value Sanitized value
*/
function tptn_sanitize_taxonomies_field( $value ) {
$taxonomies = is_array( $value ) ? array_map( 'sanitize_text_field', wp_unslash( $value ) ) : array();
return implode( ',', $taxonomies );
}
add_filter( 'tptn_settings_sanitize_taxonomies', 'tptn_sanitize_taxonomies_field' );
/**
* Sanitize exclude_cat_slugs to save a new entry of exclude_categories
*
* @since 2.5.0
*
* @param array $settings Settings array.
* @return string $settings Sanitizied settings array.
*/
function tptn_sanitize_exclude_cat( $settings ) {
if ( isset( $settings['exclude_cat_slugs'] ) ) {
$exclude_cat_slugs = array_unique( str_getcsv( $settings['exclude_cat_slugs'] ) );
foreach ( $exclude_cat_slugs as $cat_name ) {
$cat = get_term_by( 'name', $cat_name, 'category' );
// Fall back to slugs since that was the default format before v2.4.0.
if ( false === $cat ) {
$cat = get_term_by( 'slug', $cat_name, 'category' );
}
if ( isset( $cat->term_taxonomy_id ) ) {
$exclude_categories[] = $cat->term_taxonomy_id;
$exclude_categories_slugs[] = $cat->name;
}
}
$settings['exclude_categories'] = isset( $exclude_categories ) ? join( ',', $exclude_categories ) : '';
$settings['exclude_cat_slugs'] = isset( $exclude_categories_slugs ) ? tptn_str_putcsv( $exclude_categories_slugs ) : '';
}
return $settings;
}
add_filter( 'tptn_settings_sanitize', 'tptn_sanitize_exclude_cat' );
/**
* Enable/disable Top 10 cron on save.
*
* @since 2.5.0
*
* @param array $settings Settings array.
* @return string $settings Sanitizied settings array.
*/
function tptn_sanitize_cron( $settings ) {
$settings['cron_hour'] = min( 23, absint( $settings['cron_hour'] ) );
$settings['cron_min'] = min( 59, absint( $settings['cron_min'] ) );
if ( ! empty( $settings['cron_on'] ) ) {
tptn_enable_run( $settings['cron_hour'], $settings['cron_min'], $settings['cron_recurrence'] );
} else {
tptn_disable_run();
}
return $settings;
}
add_filter( 'tptn_settings_sanitize', 'tptn_sanitize_cron' );
/**
* Delete cache when saving settings.
*
* @since 2.5.0
*
* @param array $settings Settings array.
* @return string $settings Sanitizied settings array.
*/
function tptn_sanitize_cache( $settings ) {
// Delete the cache.
tptn_cache_delete();
return $settings;
}
add_filter( 'tptn_settings_sanitize', 'tptn_sanitize_cache' );

View File

@@ -0,0 +1,749 @@
<?php
/**
* Renders the settings page.
* Portions of this code have been inspired by Easy Digital Downloads, WordPress Settings Sandbox, etc.
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin/Settings
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Render the settings page.
*
* @since 2.5.0
*
* @return void
*/
function tptn_options_page() {
$active_tab = isset( $_GET['tab'] ) && array_key_exists( sanitize_key( wp_unslash( $_GET['tab'] ) ), tptn_get_settings_sections() ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
ob_start();
?>
<div class="wrap">
<h1><?php esc_html_e( 'Top 10 Settings', 'top-10' ); ?></h1>
<?php settings_errors(); ?>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<ul class="nav-tab-wrapper" style="padding:0">
<?php
foreach ( tptn_get_settings_sections() as $tab_id => $tab_name ) {
$active = $active_tab === $tab_id ? ' ' : '';
echo '<li><a href="#' . esc_attr( $tab_id ) . '" title="' . esc_attr( $tab_name ) . '" class="nav-tab ' . sanitize_html_class( $active ) . '">';
echo esc_html( $tab_name );
echo '</a></li>';
}
?>
</ul>
<form method="post" action="options.php">
<?php settings_fields( 'tptn_settings' ); ?>
<?php foreach ( tptn_get_settings_sections() as $tab_id => $tab_name ) : ?>
<div id="<?php echo esc_attr( $tab_id ); ?>">
<table class="form-table">
<?php
do_settings_fields( 'tptn_settings_' . $tab_id, 'tptn_settings_' . $tab_id );
?>
</table>
<p>
<?php
// Default submit button.
submit_button(
__( 'Save Changes', 'top-10' ),
'primary',
'submit',
false
);
echo '&nbsp;&nbsp;';
// Reset button.
$confirm = esc_js( __( 'Do you really want to reset all these settings to their default values?', 'top-10' ) );
submit_button(
__( 'Reset all settings', 'top-10' ),
'secondary',
'settings_reset',
false,
array(
'onclick' => "return confirm('{$confirm}');",
)
);
?>
</p>
</div><!-- /#tab_id-->
<?php endforeach; ?>
</form>
</div><!-- /#post-body-content -->
<div id="postbox-container-1" class="postbox-container">
<div id="side-sortables" class="meta-box-sortables ui-sortable">
<?php include_once 'sidebar.php'; ?>
</div><!-- /#side-sortables -->
</div><!-- /#postbox-container-1 -->
</div><!-- /#post-body -->
<br class="clear" />
</div><!-- /#poststuff -->
</div><!-- /.wrap -->
<?php
echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Array containing the settings' sections.
*
* @since 2.5.0
*
* @return array Settings array
*/
function tptn_get_settings_sections() {
$tptn_settings_sections = array(
'general' => __( 'General', 'top-10' ),
'counter' => __( 'Counter/Tracker', 'top-10' ),
'list' => __( 'Posts list', 'top-10' ),
'thumbnail' => __( 'Thumbnail', 'top-10' ),
'styles' => __( 'Styles', 'top-10' ),
'maintenance' => __( 'Maintenance', 'top-10' ),
'feed' => __( 'Feed', 'top-10' ),
);
/**
* Filter the array containing the settings' sections.
*
* @since 2.5.0
*
* @param array $tptn_settings_sections Settings array
*/
return apply_filters( 'tptn_settings_sections', $tptn_settings_sections );
}
/**
* Miscellaneous callback funcion
*
* @since 2.5.0
*
* @param array $args Arguments passed by the setting.
* @return void
*/
function tptn_missing_callback( $args ) {
/* translators: %s: Setting ID. */
printf( esc_html__( 'The callback function used for the <strong>%s</strong> setting is missing.', 'top-10' ), esc_html( $args['id'] ) );
}
/**
* Header Callback
*
* Renders the header.
*
* @since 2.5.0
*
* @param array $args Arguments passed by the setting.
* @return void
*/
function tptn_header_callback( $args ) {
$html = '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/**
* After Settings Output filter
*
* @since 2.5.0
* @param string $html HTML string.
* @param array $args Arguments array.
*/
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Display text fields.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_text_callback( $args ) {
// First, we read the options collection.
global $tptn_settings;
if ( isset( $tptn_settings[ $args['id'] ] ) ) {
$value = $tptn_settings[ $args['id'] ];
} else {
$value = isset( $args['options'] ) ? $args['options'] : '';
}
$size = sanitize_html_class( ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular' );
$class = sanitize_html_class( $args['field_class'] );
$disabled = ! empty( $args['disabled'] ) ? ' disabled="disabled"' : '';
$readonly = ( isset( $args['readonly'] ) && true === $args['readonly'] ) ? ' readonly="readonly"' : '';
$attributes = $disabled . $readonly;
foreach ( (array) $args['field_attributes'] as $attribute => $val ) {
$attributes .= sprintf( ' %1$s="%2$s"', $attribute, esc_attr( $val ) );
}
$html = sprintf( '<input type="text" id="tptn_settings[%1$s]" name="tptn_settings[%1$s]" class="%2$s" value="%3$s" %4$s />', sanitize_key( $args['id'] ), $class . ' ' . $size . '-text', esc_attr( stripslashes( $value ) ), $attributes );
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Display csv fields.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_csv_callback( $args ) {
tptn_text_callback( $args );
}
/**
* Display CSV fields of numbers.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_numbercsv_callback( $args ) {
tptn_csv_callback( $args );
}
/**
* Display textarea.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_textarea_callback( $args ) {
// First, we read the options collection.
global $tptn_settings;
if ( isset( $tptn_settings[ $args['id'] ] ) ) {
$value = $tptn_settings[ $args['id'] ];
} else {
$value = isset( $args['options'] ) ? $args['options'] : '';
}
$class = sanitize_html_class( $args['field_class'] );
$html = sprintf( '<textarea class="%3$s" cols="50" rows="5" id="tptn_settings[%1$s]" name="tptn_settings[%1$s]">%2$s</textarea>', sanitize_key( $args['id'] ), esc_textarea( stripslashes( $value ) ), 'large-text ' . $class );
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Display CSS fields.
*
* @since 2.5.1
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_css_callback( $args ) {
tptn_textarea_callback( $args );
}
/**
* Display checboxes.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_checkbox_callback( $args ) {
// First, we read the options collection.
global $tptn_settings;
$default = isset( $args['options'] ) ? $args['options'] : '';
$set = isset( $tptn_settings[ $args['id'] ] ) ? $tptn_settings[ $args['id'] ] : tptn_get_default_option( $args['id'] );
$checked = ! empty( $set ) ? checked( 1, (int) $set, false ) : '';
$html = sprintf( '<input type="hidden" name="tptn_settings[%1$s]" value="-1" />', sanitize_key( $args['id'] ) );
$html .= sprintf( '<input type="checkbox" id="tptn_settings[%1$s]" name="tptn_settings[%1$s]" value="1" %2$s />', sanitize_key( $args['id'] ), $checked );
$html .= ( $set <> $default ) ? '<em style="color:orange"> ' . esc_html__( 'Modified from default setting', 'top-10' ) . '</em>' : ''; // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Multicheck Callback
*
* Renders multiple checkboxes.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_multicheck_callback( $args ) {
global $tptn_settings;
$html = '';
if ( ! empty( $args['options'] ) ) {
$html .= sprintf( '<input type="hidden" name="tptn_settings[%1$s]" value="-1" />', sanitize_key( $args['id'] ) );
foreach ( $args['options'] as $key => $option ) {
if ( isset( $tptn_settings[ $args['id'] ][ $key ] ) ) {
$enabled = $key;
} else {
$enabled = null;
}
$html .= sprintf( '<input name="tptn_settings[%1$s][%2$s]" id="tptn_settings[%1$s][%2$s]" type="checkbox" value="%3$s" %4$s /> ', sanitize_key( $args['id'] ), sanitize_key( $key ), esc_attr( $key ), checked( $key, $enabled, false ) );
$html .= sprintf( '<label for="tptn_settings[%1$s][%2$s]">%3$s</label> <br />', sanitize_key( $args['id'] ), sanitize_key( $key ), $option );
}
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
}
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Radio Callback
*
* Renders radio boxes.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_radio_callback( $args ) {
global $tptn_settings;
$html = '';
foreach ( $args['options'] as $key => $option ) {
$checked = false;
if ( isset( $tptn_settings[ $args['id'] ] ) && $tptn_settings[ $args['id'] ] === $key ) {
$checked = true;
} elseif ( isset( $args['default'] ) && $args['default'] === $key && ! isset( $tptn_settings[ $args['id'] ] ) ) {
$checked = true;
}
$html .= sprintf( '<input name="tptn_settings[%1$s]" id="tptn_settings[%1$s][%2$s]" type="radio" value="%2$s" %3$s /> ', sanitize_key( $args['id'] ), $key, checked( true, $checked, false ) );
$html .= sprintf( '<label for="tptn_settings[%1$s][%2$s]">%3$s</label> <br />', sanitize_key( $args['id'] ), $key, $option );
}
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Radio callback with description.
*
* Renders radio boxes with each item having it separate description.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_radiodesc_callback( $args ) {
global $tptn_settings;
$html = '';
foreach ( $args['options'] as $option ) {
$checked = false;
if ( isset( $tptn_settings[ $args['id'] ] ) && $tptn_settings[ $args['id'] ] === $option['id'] ) {
$checked = true;
} elseif ( isset( $args['default'] ) && $args['default'] === $option['id'] && ! isset( $tptn_settings[ $args['id'] ] ) ) {
$checked = true;
}
$html .= sprintf( '<input name="tptn_settings[%1$s]" id="tptn_settings[%1$s][%2$s]" type="radio" value="%2$s" %3$s /> ', sanitize_key( $args['id'] ), $option['id'], checked( true, $checked, false ) );
$html .= sprintf( '<label for="tptn_settings[%1$s][%2$s]">%3$s</label>', sanitize_key( $args['id'] ), $option['id'], $option['name'] );
$html .= ': <em>' . wp_kses_post( $option['description'] ) . '</em> <br />';
}
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Callback for thumbnail sizes
*
* Renders list of radio boxes with various thumbnail sizes.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_thumbsizes_callback( $args ) {
global $tptn_settings;
$html = '';
if ( ! isset( $args['options']['tptn_thumbnail'] ) ) {
$args['options']['tptn_thumbnail'] = array(
'name' => 'tptn_thumbnail',
'width' => tptn_get_option( 'thumb_width', 150 ),
'height' => tptn_get_option( 'thumb_height', 150 ),
'crop' => tptn_get_option( 'thumb_crop', true ),
);
}
foreach ( $args['options'] as $option ) {
$checked = false;
if ( isset( $tptn_settings[ $args['id'] ] ) && $tptn_settings[ $args['id'] ] === $option['name'] ) {
$checked = true;
} elseif ( isset( $args['default'] ) && $args['default'] === $option['name'] && ! isset( $tptn_settings[ $args['id'] ] ) ) {
$checked = true;
}
$html .= sprintf( '<input name="tptn_settings[%1$s]" id="tptn_settings[%1$s][%2$s]" type="radio" value="%2$s" %3$s /> ', sanitize_key( $args['id'] ), $option['name'], checked( true, $checked, false ) );
$html .= sprintf( '<label for="tptn_settings[%1$s][%2$s]">%3$s</label> <br />', sanitize_key( $args['id'] ), $option['name'], $option['name'] . ' (' . $option['width'] . 'x' . $option['height'] . ')' );
}
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Number Callback
*
* Renders number fields.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_number_callback( $args ) {
global $tptn_settings;
if ( isset( $tptn_settings[ $args['id'] ] ) ) {
$value = $tptn_settings[ $args['id'] ];
} else {
$value = isset( $args['options'] ) ? $args['options'] : '';
}
$max = isset( $args['max'] ) ? $args['max'] : 999999;
$min = isset( $args['min'] ) ? $args['min'] : 0;
$step = isset( $args['step'] ) ? $args['step'] : 1;
$size = ( isset( $args['size'] ) && ! is_null( $args['size'] ) ) ? $args['size'] : 'regular';
$html = sprintf( '<input type="number" step="%1$s" max="%2$s" min="%3$s" class="%4$s" id="tptn_settings[%5$s]" name="tptn_settings[%5$s]" value="%6$s"/>', esc_attr( $step ), esc_attr( $max ), esc_attr( $min ), sanitize_html_class( $size ) . '-text', sanitize_key( $args['id'] ), esc_attr( stripslashes( $value ) ) );
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Select Callback
*
* Renders select fields.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_select_callback( $args ) {
global $tptn_settings;
if ( isset( $tptn_settings[ $args['id'] ] ) ) {
$value = $tptn_settings[ $args['id'] ];
} else {
$value = isset( $args['default'] ) ? $args['default'] : '';
}
if ( isset( $args['chosen'] ) ) {
$chosen = 'class="tptn-chosen"';
} else {
$chosen = '';
}
$html = sprintf( '<select id="tptn_settings[%1$s]" name="tptn_settings[%1$s]" %2$s />', sanitize_key( $args['id'] ), $chosen );
foreach ( $args['options'] as $option => $name ) {
$html .= sprintf( '<option value="%1$s" %2$s>%3$s</option>', sanitize_key( $option ), selected( $option, $value, false ), $name );
}
$html .= '</select>';
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Descriptive text callback.
*
* Renders descriptive text onto the settings field.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_descriptive_text_callback( $args ) {
$html = '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Display csv fields.
*
* @since 2.5.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_posttypes_callback( $args ) {
global $tptn_settings;
$html = '';
if ( isset( $tptn_settings[ $args['id'] ] ) ) {
$options = $tptn_settings[ $args['id'] ];
} else {
$options = isset( $args['options'] ) ? $args['options'] : '';
}
// If post_types is empty or contains a query string then use parse_str else consider it comma-separated.
if ( is_array( $options ) ) {
$post_types = $options;
} elseif ( ! is_array( $options ) && false === strpos( $options, '=' ) ) {
$post_types = explode( ',', $options );
} else {
parse_str( $options, $post_types );
}
$wp_post_types = get_post_types(
array(
'public' => true,
)
);
$posts_types_inc = array_intersect( $wp_post_types, $post_types );
$html .= sprintf( '<input type="hidden" name="tptn_settings[%1$s]" value="-1" />', sanitize_key( $args['id'] ) );
foreach ( $wp_post_types as $wp_post_type ) {
$html .= sprintf( '<input name="tptn_settings[%1$s][%2$s]" id="tptn_settings[%1$s][%2$s]" type="checkbox" value="%2$s" %3$s /> ', sanitize_key( $args['id'] ), esc_attr( $wp_post_type ), checked( true, in_array( $wp_post_type, $posts_types_inc, true ), false ) );
$html .= sprintf( '<label for="tptn_settings[%1$s][%2$s]">%2$s</label> <br />', sanitize_key( $args['id'] ), $wp_post_type );
}
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Display taxonomies fields.
*
* @since 3.0.0
*
* @param array $args Array of arguments.
* @return void
*/
function tptn_taxonomies_callback( $args ) {
global $tptn_settings;
$html = '';
if ( isset( $tptn_settings[ $args['id'] ] ) ) {
$options = $tptn_settings[ $args['id'] ];
} else {
$options = isset( $args['options'] ) ? $args['options'] : '';
}
// If taxonomies is empty or contains a query string then use parse_str else consider it comma-separated.
if ( is_array( $options ) ) {
$taxonomies = $options;
} elseif ( ! is_array( $options ) && false === strpos( $options, '=' ) ) {
$taxonomies = explode( ',', $options );
} else {
parse_str( $options, $taxonomies );
}
/* Fetch taxonomies */
$argsc = array(
'public' => true,
);
$output = 'objects';
$operator = 'and';
$wp_taxonomies = get_taxonomies( $argsc, $output, $operator );
$taxonomies_inc = array_intersect( wp_list_pluck( (array) $wp_taxonomies, 'name' ), $taxonomies );
$html .= sprintf( '<input type="hidden" name="tptn_settings[%1$s]" value="-1" />', sanitize_key( $args['id'] ) );
foreach ( $wp_taxonomies as $wp_taxonomy ) {
$html .= sprintf( '<input name="tptn_settings[%1$s][%2$s]" id="tptn_settings[%1$s][%2$s]" type="checkbox" value="%2$s" %3$s /> ', sanitize_key( $args['id'] ), esc_attr( $wp_taxonomy->name ), checked( true, in_array( $wp_taxonomy->name, $taxonomies_inc, true ), false ) );
$html .= sprintf( '<label for="tptn_settings[%1$s][%2$s]">%3$s (%4$s)</label> <br />', sanitize_key( $args['id'] ), esc_attr( $wp_taxonomy->name ), $wp_taxonomy->labels->name, $wp_taxonomy->name );
}
$html .= '<p class="description">' . wp_kses_post( $args['desc'] ) . '</p>';
/** This filter has been defined in settings-page.php */
echo apply_filters( 'tptn_after_setting_output', $html, $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Function to add an action to search for tags using Ajax.
*
* @since 2.1.0
*
* @return void
*/
function tptn_tags_search() {
if ( ! isset( $_REQUEST['tax'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
wp_die( 0 );
}
$taxonomy = sanitize_key( $_REQUEST['tax'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$tax = get_taxonomy( $taxonomy );
if ( ! $tax ) {
wp_die( 0 );
}
if ( ! current_user_can( $tax->cap->assign_terms ) ) {
wp_die( -1 );
}
$s = isset( $_REQUEST['q'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['q'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$comma = _x( ',', 'tag delimiter' );
if ( ',' !== $comma ) {
$s = str_replace( $comma, ',', $s );
}
if ( false !== strpos( $s, ',' ) ) {
$s = explode( ',', $s );
$s = $s[ count( $s ) - 1 ];
}
$s = trim( $s );
/** This filter has been defined in /wp-admin/includes/ajax-actions.php */
$term_search_min_chars = (int) apply_filters( 'term_search_min_chars', 2, $tax, $s );
/*
* Require $term_search_min_chars chars for matching (default: 2)
* ensure it's a non-negative, non-zero integer.
*/
if ( ( 0 === $term_search_min_chars ) || ( strlen( $s ) < $term_search_min_chars ) ) {
wp_die();
}
$results = get_terms(
array(
'taxonomy' => $taxonomy,
'name__like' => $s,
'fields' => 'names',
'hide_empty' => false,
)
);
echo wp_json_encode( $results );
wp_die();
}
add_action( 'wp_ajax_tptn_tag_search', 'tptn_tags_search' );
/**
* Display the default thumbnail below the setting.
*
* @since 2.1.0
*
* @param string $html Current HTML.
* @param array $args Argument array of the setting.
* @return string
*/
function tptn_admin_thumbnail( $html, $args ) {
$thumb_default = tptn_get_option( 'thumb_default' );
if ( 'thumb_default' === $args['id'] && '' !== $thumb_default ) {
$html .= '<br />';
$html .= sprintf( '<img src="%1$s" style="max-width:200px" title="%2$s" alt="%2$s" />', esc_attr( $thumb_default ), esc_html__( 'Default thumbnail', 'where-did-they-go-from-here' ) );
}
return $html;
}
add_filter( 'tptn_after_setting_output', 'tptn_admin_thumbnail', 10, 2 );

View File

@@ -0,0 +1,96 @@
<?php
/**
* Sidebar
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin/Footer
*/
?>
<div class="postbox-container">
<div id="donatediv" class="postbox meta-box-sortables">
<h2 class='hndle'><span><?php esc_html_e( 'Support the development', 'top-10' ); ?></span></h3>
<div class="inside" style="text-align: center">
<div id="donate-form">
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="donate@ajaydsouza.com">
<input type="hidden" name="lc" value="IN">
<input type="hidden" name="item_name" value="<?php esc_html_e( 'Donation for Top 10', 'top-10' ); ?>">
<input type="hidden" name="item_number" value="crp_plugin_settings">
<strong><?php esc_html_e( 'Enter amount in USD', 'top-10' ); ?></strong>: <input name="amount" value="15.00" size="6" type="text"><br />
<input type="hidden" name="currency_code" value="USD">
<input type="hidden" name="button_subtype" value="services">
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_donate_LG.gif:NonHosted">
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="<?php esc_html_e( 'Send your donation to the author of', 'top-10' ); ?> Top 10">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
</div>
<!-- /#donate-form -->
</div>
<!-- /.inside -->
</div>
<!-- /.postbox -->
<div id="qlinksdiv" class="postbox meta-box-sortables">
<h2 class='hndle metabox-holder'><span><?php esc_html_e( 'Quick links', 'top-10' ); ?></span></h3>
<div class="inside">
<div id="quick-links">
<ul>
<li>
<a href="https://webberzone.com/plugins/top-10/">
<?php esc_html_e( 'Top 10 plugin homepage', 'top-10' ); ?>
</a>
</li>
<li>
<a href="https://wordpress.org/plugins/top-10/faq/">
<?php esc_html_e( 'FAQ', 'top-10' ); ?>
</a>
</li>
<li>
<a href="http://wordpress.org/support/plugin/top-10">
<?php esc_html_e( 'Support', 'top-10' ); ?>
</a>
</li>
<li>
<a href="https://wordpress.org/support/view/plugin-reviews/top-10">
<?php esc_html_e( 'Reviews', 'top-10' ); ?>
</a>
</li>
<li>
<a href="https://github.com/WebberZone/top-10">
<?php esc_html_e( 'Github repository', 'top-10' ); ?>
</a>
</li>
<li>
<a href="https://webberzone.com/plugins/">
<?php esc_html_e( 'Other plugins', 'top-10' ); ?>
</a>
</li>
<li>
<a href="https://ajaydsouza.com/">
<?php esc_html_e( "Ajay's blog", 'top-10' ); ?>
</a>
</li>
</ul>
</div>
</div>
<!-- /.inside -->
</div>
<!-- /.postbox -->
</div>
<div class="postbox-container">
<div id="followdiv" class="postbox meta-box-sortables">
<h2 class='hndle'><span><?php esc_html_e( 'Follow me', 'add-to-all' ); ?></span></h3>
<div class="inside" style="text-align: center">
<a href="https://facebook.com/webberzone/" target="_blank"><img src="<?php echo esc_url( TOP_TEN_PLUGIN_URL . 'includes/admin/images/fb.png' ); ?>" width="100" height="100" /></a>
<a href="https://twitter.com/webberzonewp/" target="_blank"><img src="<?php echo esc_url( TOP_TEN_PLUGIN_URL . 'includes/admin/images/twitter.jpg' ); ?>" width="100" height="100" /></a>
</div>
<!-- /.inside -->
</div>
<!-- /.postbox -->
</div>

View File

@@ -0,0 +1,345 @@
<?php
/**
* The admin-specific functionality of the plugin.
*
* @link https://webberzone.com
* @since 2.5.0
*
* @package Top 10
* @subpackage Admin/Tools
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Render the tools settings page.
*
* @since 2.5.0
*
* @return void
*/
function tptn_tools_page() {
/* Truncate overall posts table */
if ( ( isset( $_POST['tptn_recreate_primary_key'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
tptn_recreate_primary_key();
add_settings_error( 'tptn-notices', '', esc_html__( 'Primary Key has been recreated', 'top-10' ), 'error' );
}
/* Truncate overall posts table */
if ( ( isset( $_POST['tptn_trunc_all'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
tptn_trunc_count( false );
add_settings_error( 'tptn-notices', '', esc_html__( 'Top 10 popular posts reset', 'top-10' ), 'error' );
}
/* Recreate tables */
if ( ( isset( $_POST['tptn_recreate_tables'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
tptn_recreate_tables();
add_settings_error( 'tptn-notices', '', esc_html__( 'Top 10 tables have been recreated', 'top-10' ), 'updated' );
}
/* Truncate daily posts table */
if ( ( isset( $_POST['tptn_trunc_daily'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
tptn_trunc_count( true );
add_settings_error( 'tptn-notices', '', esc_html__( 'Top 10 daily popular posts reset', 'top-10' ), 'error' );
}
/* Delete old settings */
if ( ( isset( $_POST['tptn_delete_old_settings'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
delete_option( 'ald_tptn_settings' );
add_settings_error( 'tptn-notices', '', esc_html__( 'Old settings key has been deleted', 'top-10' ), 'error' );
}
/* Clean duplicates */
if ( ( isset( $_POST['tptn_clean_duplicates'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
tptn_clean_duplicates( true );
tptn_clean_duplicates( false );
add_settings_error( 'tptn-notices', '', esc_html__( 'Duplicate rows cleaned from the tables', 'top-10' ), 'error' );
}
/* Merge blog IDs */
if ( ( isset( $_POST['tptn_merge_blogids'] ) ) && ( check_admin_referer( 'tptn-tools-settings' ) ) ) {
tptn_merge_blogids( true );
tptn_merge_blogids( false );
add_settings_error( 'tptn-notices', '', esc_html__( 'Post counts across blog IDs 0 and 1 have been merged', 'top-10' ), 'error' );
}
ob_start();
?>
<div class="wrap">
<h1><?php esc_html_e( 'Top 10 Tools', 'top-10' ); ?></h1>
<?php settings_errors(); ?>
<div id="poststuff">
<div id="post-body" class="metabox-holder columns-2">
<div id="post-body-content">
<form method="post" >
<h2 style="padding-left:0px"><?php esc_html_e( 'Clear cache', 'top-10' ); ?></h2>
<p>
<input type="button" name="cache_clear" id="cache_clear" value="<?php esc_attr_e( 'Clear cache', 'top-10' ); ?>" class="button button-secondary" onclick="return clearCache();" />
</p>
<p class="description">
<?php esc_html_e( 'Clear the Top 10 cache. This will also be cleared automatically when you save the settings page.', 'top-10' ); ?>
</p>
<h2 style="padding-left:0px"><?php esc_html_e( 'Recreate Primary Key', 'top-10' ); ?></h2>
<p>
<input name="tptn_recreate_primary_key" type="submit" id="tptn_recreate_primary_key" value="<?php esc_attr_e( 'Recreate Primary Key', 'top-10' ); ?>" class="button button-secondary" />
</p>
<p class="description">
<?php esc_html_e( 'Deletes and reinitializes the primary key in the database tables. If the above function gives an error, then you can run the below code in phpMyAdmin or Adminer. Remember to backup your database first!', 'top-10' ); ?>
</p>
<p>
<code style="display:block;"><?php echo tptn_recreate_primary_key_html(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></code>
</p>
<h2 style="padding-left:0px"><?php esc_html_e( 'Reset database', 'top-10' ); ?></h2>
<p class="description">
<?php esc_html_e( 'This will reset the Top 10 tables. If you are running Top 10 on multisite then it will delete the popular posts across the entire network. This cannot be reversed. Make sure that your database has been backed up before proceeding', 'top-10' ); ?>
</p>
<p>
<input name="tptn_trunc_all" type="submit" id="tptn_trunc_all" value="<?php esc_attr_e( 'Reset Popular Posts Network-wide', 'top-10' ); ?>" class="button button-secondary" style="color:#f00" onclick="if (!confirm('<?php esc_attr_e( 'Are you sure you want to reset the popular posts?', 'top-10' ); ?>')) return false;" />
<input name="tptn_trunc_daily" type="submit" id="tptn_trunc_daily" value="<?php esc_attr_e( 'Reset Daily Popular Posts Network-wide', 'top-10' ); ?>" class="button button-secondary" style="color:#f00" onclick="if (!confirm('<?php esc_attr_e( 'Are you sure you want to reset the daily popular posts?', 'top-10' ); ?>')) return false;" />
</p>
<h2 style="padding-left:0px"><?php esc_html_e( 'Recreate Database Tables', 'top-10' ); ?></h2>
<p class="description">
<?php esc_html_e( 'Only click the button below after performing a full backup of the database. You can use any of the popular backup plugins or phpMyAdmin to achieve this. The authors of this plugin do not guarantee that everything will go smoothly as it depends on your site environment and volume of data. If you are not comfortable, please do not proceed.', 'top-10' ); ?>
</p>
<p>
<input name="tptn_recreate_tables" type="submit" id="tptn_recreate_tables" value="<?php esc_attr_e( 'Recreate Database Tables', 'top-10' ); ?>" style="color:#f00" onclick="if (!confirm('<?php esc_attr_e( 'Hit Cancel if you have not backed up your database', 'top-10' ); ?>')) return false;" class="button button-secondary" />
</p>
<h2 style="padding-left:0px"><?php esc_html_e( 'Other tools', 'top-10' ); ?></h2>
<p class="description">
<?php esc_html_e( 'From v2.5.x, Top 10 stores the settings in a new key in the database. This will delete the old settings for the current blog. It is recommended that you do this at the earliest after upgrade. However, you should do this only if you are comfortable with the new settings.', 'top-10' ); ?>
</p>
<p>
<input name="tptn_delete_old_settings" type="submit" id="tptn_delete_old_settings" value="<?php esc_attr_e( 'Delete old settings', 'top-10' ); ?>" class="button button-secondary" onclick="if (!confirm('<?php esc_attr_e( 'This will delete the settings before v2.5.x. Proceed?', 'top-10' ); ?>')) return false;" />
</p>
<p class="description">
<?php esc_html_e( 'This will merge post counts for posts with table entries of 0 and 1', 'top-10' ); ?>
</p>
<p>
<input name="tptn_merge_blogids" type="submit" id="tptn_merge_blogids" value="<?php esc_attr_e( 'Merge blog ID 0 and 1 post counts', 'top-10' ); ?>" class="button button-secondary" onclick="if (!confirm('<?php esc_attr_e( 'This will merge post counts for blog IDs 0 and 1. Proceed?', 'top-10' ); ?>')) return false;" />
</p>
<p class="description">
<?php esc_html_e( 'In older versions, the plugin created entries with duplicate post IDs. Clicking the button below will merge these duplicate IDs', 'top-10' ); ?>
</p>
<p>
<input name="tptn_clean_duplicates" type="submit" id="tptn_clean_duplicates" value="<?php esc_attr_e( 'Merge duplicates across blog IDs', 'top-10' ); ?>" class="button button-secondary" onclick="if (!confirm('<?php esc_attr_e( 'This will delete the duplicate entries in the tables. Proceed?', 'top-10' ); ?>')) return false;" />
</p>
<?php wp_nonce_field( 'tptn-tools-settings' ); ?>
</form>
</div><!-- /#post-body-content -->
<div id="postbox-container-1" class="postbox-container">
<div id="side-sortables" class="meta-box-sortables ui-sortable">
<?php include_once 'sidebar.php'; ?>
</div><!-- /#side-sortables -->
</div><!-- /#postbox-container-1 -->
</div><!-- /#post-body -->
<br class="clear" />
</div><!-- /#poststuff -->
</div><!-- /.wrap -->
<?php
echo ob_get_clean(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Function to delete all duplicate rows in the posts table.
*
* @since 1.6.2
*
* @param bool $daily Daily flag.
*/
function tptn_clean_duplicates( $daily = false ) {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
if ( $daily ) {
$table_name .= '_daily';
}
$wpdb->query( 'CREATE TEMPORARY TABLE ' . $table_name . '_temp AS SELECT * FROM ' . $table_name . ' GROUP BY postnumber' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
$wpdb->query( "TRUNCATE TABLE $table_name" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query( 'INSERT INTO ' . $table_name . ' SELECT * FROM ' . $table_name . '_temp' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Function to merge counts with post numbers of blog ID 0 and 1 respectively.
*
* @since 2.0.4
*
* @param bool $daily Daily flag.
*/
function tptn_merge_blogids( $daily = false ) {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
if ( $daily ) {
$table_name .= '_daily';
}
if ( $daily ) {
$sql = "
INSERT INTO `$table_name` (postnumber, cntaccess, dp_date, blog_id) (
SELECT
postnumber,
SUM(cntaccess) as sumCount,
dp_date,
1
FROM `$table_name`
WHERE blog_ID IN (0,1)
GROUP BY postnumber, dp_date
) ON DUPLICATE KEY UPDATE cntaccess = VALUES(cntaccess);
";
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
} else {
$sql = "
INSERT INTO `$table_name` (postnumber, cntaccess, blog_id) (
SELECT
postnumber,
SUM(cntaccess) as sumCount,
1
FROM `$table_name`
WHERE blog_ID IN (0,1)
GROUP BY postnumber
) ON DUPLICATE KEY UPDATE cntaccess = VALUES(cntaccess);
";
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
}
$wpdb->query( "DELETE FROM $table_name WHERE blog_id = 0" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
/**
* Function to delete and create the primary keys in the database table.
*
* @since 2.5.6
*/
function tptn_recreate_primary_key() {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
$wpdb->hide_errors();
if ( $wpdb->query( $wpdb->prepare( "SHOW INDEXES FROM {$table_name} WHERE Key_name = %s", 'PRIMARY' ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query( 'ALTER TABLE ' . $table_name . ' DROP PRIMARY KEY ' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
}
if ( $wpdb->query( $wpdb->prepare( "SHOW INDEXES FROM {$table_name_daily} WHERE Key_name = %s", 'PRIMARY' ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query( 'ALTER TABLE ' . $table_name_daily . ' DROP PRIMARY KEY ' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
}
$wpdb->query( 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY(postnumber, blog_id) ' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
$wpdb->query( 'ALTER TABLE ' . $table_name_daily . ' ADD PRIMARY KEY(postnumber, dp_date, blog_id) ' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange
$wpdb->show_errors();
}
/**
* Retrieves the SQL code to recreate the PRIMARY KEY.
*
* @since 2.5.7
*/
function tptn_recreate_primary_key_html() {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
$sql = 'ALTER TABLE ' . $table_name . ' DROP PRIMARY KEY; ';
$sql .= '<br />';
$sql .= 'ALTER TABLE ' . $table_name_daily . ' DROP PRIMARY KEY; ';
$sql .= '<br />';
$sql .= 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY(postnumber, blog_id); ';
$sql .= '<br />';
$sql .= 'ALTER TABLE ' . $table_name_daily . ' ADD PRIMARY KEY(postnumber, dp_date, blog_id); ';
/**
* Filters the SQL code to recreate the PRIMARY KEY.
*
* @since 2.5.7
* @param string $sql SQL code to recreate PRIMARY KEY.
*/
return apply_filters( 'tptn_recreate_primary_key_html', $sql );
}
/**
* Retrieves the SQL code to recreate the PRIMARY KEY.
*
* @since 2.7.0
*/
function tptn_recreate_tables() {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
$table_name_temp = $table_name . '_temp';
$table_name_daily_temp = $table_name_daily . '_temp';
$wpdb->hide_errors();
// 1. create temporary tables with the data.
$wpdb->query( "CREATE TEMPORARY TABLE {$table_name_temp} SELECT * FROM $table_name;" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query( "CREATE TEMPORARY TABLE {$table_name_daily_temp} SELECT * FROM $table_name_daily;" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
// 2. Drop the tables.
$wpdb->query( "DROP TABLE $table_name" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$wpdb->query( "DROP TABLE $table_name_daily" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
// 3. Run the activation function which will recreate the tables.
tptn_single_activate();
// 4. Reinsert the data from the temporary table.
$sql = "
INSERT INTO `$table_name` (postnumber, cntaccess, blog_id) (
SELECT
postnumber,
cntaccess,
blog_id
FROM `$table_name_temp`
);
";
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$sql = "
INSERT INTO `$table_name_daily` (postnumber, cntaccess, dp_date, blog_id) (
SELECT
postnumber,
cntaccess,
dp_date,
blog_id
FROM `$table_name_daily_temp`
);
";
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
// 5. Drop the temporary tables.
$wpdb->query( "DROP TABLE $table_name_temp" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$wpdb->query( "DROP TABLE $table_name_daily_temp" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$wpdb->show_errors();
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,157 @@
<?php
/**
* Functions to register client-side assets (scripts and stylesheets) for the
* Gutenberg block.
*
* @package Top_Ten
*/
/**
* Renders the `top-10/popular-posts` block on server.
*
* @since 3.0.0
* @param array $attributes The block attributes.
*
* @return string Returns the post content with popular posts added.
*/
function render_tptn_block( $attributes ) {
$attributes['extra_class'] = $attributes['className'];
$arguments = array_merge(
$attributes,
array(
'is_block' => 1,
)
);
$arguments = wp_parse_args( $attributes['other_attributes'], $arguments );
/**
* Filters arguments passed to get_tptn for the block.
*
* @since 3.0.0
*
* @param array $arguments Top 10 block options array.
* @param array $attributes Block attributes array.
*/
$arguments = apply_filters( 'tptn_block_options', $arguments, $attributes );
return tptn_pop_posts( $arguments );
}
/**
* Registers all block assets so that they can be enqueued through Gutenberg in
* the corresponding context.
*
* @since 3.0.0
*/
function tptn_block_init() {
// Skip block registration if Gutenberg is not enabled/merged.
if ( ! function_exists( 'register_block_type' ) ) {
return;
}
$dir = dirname( __FILE__ );
$index_js = 'popular-posts/index.min.js';
wp_register_script( // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NotInFooter
'popular-posts-block-editor',
plugins_url( $index_js, __FILE__ ),
array(
'wp-blocks',
'wp-i18n',
'wp-element',
'wp-components',
'wp-block-editor',
'wp-editor',
),
filemtime( "$dir/$index_js" )
);
$style_array = tptn_get_style();
if ( ! empty( $style_array ) ) {
$style = $style_array['name'];
$extra_css = $style_array['extra_css'];
wp_register_style(
'popular-posts-block-editor',
plugins_url( "css/{$style}.min.css", TOP_TEN_PLUGIN_FILE ),
array( 'wp-edit-blocks' ),
'1.0'
);
wp_add_inline_style( 'popular-posts-block-editor', $extra_css );
}
$args = array(
'editor_script' => 'popular-posts-block-editor',
'render_callback' => 'render_tptn_block',
'attributes' => array(
'className' => array(
'type' => 'string',
'default' => '',
),
'heading' => array(
'type' => 'boolean',
'default' => false,
),
'daily' => array(
'type' => 'boolean',
'default' => false,
),
'daily_range' => array(
'type' => 'number',
'default' => 1,
),
'hour_range' => array(
'type' => 'number',
'default' => 0,
),
'limit' => array(
'type' => 'number',
'default' => 6,
),
'offset' => array(
'type' => 'number',
'default' => 0,
),
'show_excerpt' => array(
'type' => 'boolean',
'default' => false,
),
'show_author' => array(
'type' => 'boolean',
'default' => false,
),
'show_date' => array(
'type' => 'boolean',
'default' => false,
),
'disp_list_count' => array(
'type' => 'boolean',
'default' => false,
),
'post_thumb_op' => array(
'type' => 'string',
'default' => 'inline',
),
'other_attributes' => array(
'type' => 'string',
'default' => '',
),
),
);
if ( ! empty( $style ) ) {
$args['editor_style'] = 'popular-posts-block-editor';
}
register_block_type(
'top-10/popular-posts',
$args
);
if ( function_exists( 'wp_set_script_translations' ) ) {
wp_set_script_translations( 'popular-posts-block-editor', 'top-10' );
}
}
add_action( 'init', 'tptn_block_init' );

View File

@@ -0,0 +1,250 @@
( function( blocks, i18n, element, components, editor, blockEditor ) {
var el = element.createElement;
const {registerBlockType} = blocks;
const {__} = i18n; //translation functions
var ServerSideRender = wp.serverSideRender;
const { RichText, InspectorControls } = blockEditor;
const {
TextControl,
CheckboxControl,
RadioControl,
SelectControl,
TextareaControl,
ToggleControl,
RangeControl,
Panel,
PanelBody,
PanelRow,
} = components;
registerBlockType( 'top-10/popular-posts', {
title: __( 'Popular Posts [Top 10]', 'top-10' ),
description: __( 'Display popular posts by Top 10', 'top-10' ),
category: 'widgets',
icon: 'editor-ol',
keywords: [ __( 'popular posts' ), __( 'popular' ), __( 'posts' ) ],
attributes: {
heading: {
type: 'boolean',
default: false,
},
daily: {
type: 'boolean',
default: false,
},
daily_range: {
type: 'number',
default: 1,
},
hour_range: {
type: 'number',
default: 0,
},
limit: {
type: 'number',
default: 6,
},
offset: {
type: 'number',
default: 0,
},
show_excerpt: {
type: 'boolean',
default: false,
},
show_author: {
type: 'boolean',
default: false,
},
show_date: {
type: 'boolean',
default: false,
},
disp_list_count: {
type: 'boolean',
default: false,
},
post_thumb_op: {
type: 'string',
default: 'inline',
},
other_attributes: {
type: 'string',
default: '',
},
},
supports: {
html: false,
},
example: { },
edit: function( props ) {
const attributes = props.attributes;
const setAttributes = props.setAttributes;
if(props.isSelected){
// console.debug(props.attributes);
};
// Functions to update attributes.
function changeHeading(heading){
setAttributes({heading});
}
function changeExcerpt(show_excerpt){
setAttributes({show_excerpt});
}
function changeDaily(daily){
setAttributes({daily});
}
function changeAuthor(show_author){
setAttributes({show_author});
}
function changeDate(show_date){
setAttributes({show_date});
}
function changeDisplayCount(disp_list_count){
setAttributes({disp_list_count});
}
function changeThumbnail(post_thumb_op){
setAttributes({post_thumb_op});
}
function changeOtherAttributes(other_attributes){
setAttributes({other_attributes});
}
return [
/**
* Server side render
*/
el("div", { className: props.className },
el( ServerSideRender, {
block: 'top-10/popular-posts',
attributes: attributes
} )
),
/**
* Inspector
*/
el( InspectorControls, {},
el( PanelBody, { title: 'Related Posts Settings', initialOpen: true },
el( ToggleControl, {
label: __( 'Show heading', 'top-10' ),
checked: attributes.heading,
onChange: changeHeading
} ),
el( ToggleControl, {
label: __( 'Custom period? Set range below', 'top-10' ),
checked: attributes.daily,
onChange: changeDaily
} ),
el( TextControl, {
label: __( 'Daily range', 'top-10' ),
value: attributes.daily_range,
onChange: function( val ) {
setAttributes( { daily_range: parseInt( val ) } );
},
type: 'number',
min: 0,
step: 1
} ),
el( TextControl, {
label: __( 'Hourly range', 'top-10' ),
value: attributes.hour_range,
onChange: function( val ) {
setAttributes( { hour_range: parseInt( val ) } );
},
type: 'number',
min: 0,
step: 1
} ),
el( TextControl, {
label: __( 'No. of posts', 'top-10' ),
value: attributes.limit,
onChange: function( val ) {
setAttributes( { limit: parseInt( val ) } );
},
type: 'number',
min: 1,
step: 1
} ),
el( TextControl, {
label: __( 'Offset', 'top-10' ),
value: attributes.offset,
onChange: function( val ) {
setAttributes( { offset: parseInt( val ) } );
},
type: 'number',
min: 0,
step: 1
}),
el( ToggleControl, {
label: __( 'Show excerpt', 'top-10' ),
checked: attributes.show_excerpt,
onChange: changeExcerpt
} ),
el( ToggleControl, {
label: __( 'Show author', 'top-10' ),
checked: attributes.show_author,
onChange: changeAuthor
} ),
el( ToggleControl, {
label: __( 'Show date', 'top-10' ),
checked: attributes.show_date,
onChange: changeDate
} ),
el( ToggleControl, {
label: __( 'Show count', 'top-10' ),
checked: attributes.disp_list_count,
onChange: changeDisplayCount
} ),
el(SelectControl, {
value: attributes.post_thumb_op,
label: __( 'Thumbnail options', 'top-10' ),
onChange: changeThumbnail,
options: [
{value: 'inline', label: __( 'Before title', 'top-10' )},
{value: 'after', label: __( 'After title', 'top-10' )},
{value: 'thumbs_only', label: __( 'Only thumbnail', 'top-10' )},
{value: 'text_only', label: __( 'Only text', 'top-10' )},
]
} ),
el( TextareaControl, {
label: __( 'Other attributes', 'top-10' ),
help: __( 'Enter other attributes in a URL-style string-query. e.g. post_types=post,page&link_nofollow=1&exclude_post_ids=5,6', 'top-10' ),
value: attributes.other_attributes,
onChange: changeOtherAttributes
} )
),
),
]
},
save(){
return null;//save has to exist. This all we need
}
} );
} )(
window.wp.blocks,
window.wp.i18n,
window.wp.element,
window.wp.components,
window.wp.editor,
window.wp.blockEditor,
window.wp.serverSideRender
);

View File

@@ -0,0 +1 @@
!function(blocks,i18n,element,components,editor,blockEditor){var el=element.createElement;const{registerBlockType:registerBlockType}=blocks,{__:__}=i18n;var ServerSideRender=wp.serverSideRender;const{RichText:RichText,InspectorControls:InspectorControls}=blockEditor,{TextControl:TextControl,CheckboxControl:CheckboxControl,RadioControl:RadioControl,SelectControl:SelectControl,TextareaControl:TextareaControl,ToggleControl:ToggleControl,RangeControl:RangeControl,Panel:Panel,PanelBody:PanelBody,PanelRow:PanelRow}=components;registerBlockType("top-10/popular-posts",{title:__("Popular Posts [Top 10]","top-10"),description:__("Display popular posts by Top 10","top-10"),category:"widgets",icon:"editor-ol",keywords:[__("popular posts"),__("popular"),__("posts")],attributes:{heading:{type:"boolean",default:!1},daily:{type:"boolean",default:!1},daily_range:{type:"number",default:1},hour_range:{type:"number",default:0},limit:{type:"number",default:6},offset:{type:"number",default:0},show_excerpt:{type:"boolean",default:!1},show_author:{type:"boolean",default:!1},show_date:{type:"boolean",default:!1},disp_list_count:{type:"boolean",default:!1},post_thumb_op:{type:"string",default:"inline"},other_attributes:{type:"string",default:""}},supports:{html:!1},example:{},edit:function(props){const attributes=props.attributes,setAttributes=props.setAttributes;function changeHeading(heading){setAttributes({heading:heading})}function changeExcerpt(show_excerpt){setAttributes({show_excerpt:show_excerpt})}function changeDaily(daily){setAttributes({daily:daily})}function changeAuthor(show_author){setAttributes({show_author:show_author})}function changeDate(show_date){setAttributes({show_date:show_date})}function changeDisplayCount(disp_list_count){setAttributes({disp_list_count:disp_list_count})}function changeThumbnail(post_thumb_op){setAttributes({post_thumb_op:post_thumb_op})}function changeOtherAttributes(other_attributes){setAttributes({other_attributes:other_attributes})}return props.isSelected,[el("div",{className:props.className},el(ServerSideRender,{block:"top-10/popular-posts",attributes:attributes})),el(InspectorControls,{},el(PanelBody,{title:"Related Posts Settings",initialOpen:!0},el(ToggleControl,{label:__("Show heading","top-10"),checked:attributes.heading,onChange:changeHeading}),el(ToggleControl,{label:__("Custom period? Set range below","top-10"),checked:attributes.daily,onChange:changeDaily}),el(TextControl,{label:__("Daily range","top-10"),value:attributes.daily_range,onChange:function(val){setAttributes({daily_range:parseInt(val)})},type:"number",min:0,step:1}),el(TextControl,{label:__("Hourly range","top-10"),value:attributes.hour_range,onChange:function(val){setAttributes({hour_range:parseInt(val)})},type:"number",min:0,step:1}),el(TextControl,{label:__("No. of posts","top-10"),value:attributes.limit,onChange:function(val){setAttributes({limit:parseInt(val)})},type:"number",min:1,step:1}),el(TextControl,{label:__("Offset","top-10"),value:attributes.offset,onChange:function(val){setAttributes({offset:parseInt(val)})},type:"number",min:0,step:1}),el(ToggleControl,{label:__("Show excerpt","top-10"),checked:attributes.show_excerpt,onChange:changeExcerpt}),el(ToggleControl,{label:__("Show author","top-10"),checked:attributes.show_author,onChange:changeAuthor}),el(ToggleControl,{label:__("Show date","top-10"),checked:attributes.show_date,onChange:changeDate}),el(ToggleControl,{label:__("Show count","top-10"),checked:attributes.disp_list_count,onChange:changeDisplayCount}),el(SelectControl,{value:attributes.post_thumb_op,label:__("Thumbnail options","top-10"),onChange:changeThumbnail,options:[{value:"inline",label:__("Before title","top-10")},{value:"after",label:__("After title","top-10")},{value:"thumbs_only",label:__("Only thumbnail","top-10")},{value:"text_only",label:__("Only text","top-10")}]}),el(TextareaControl,{label:__("Other attributes","top-10"),help:__("Enter other attributes in a URL-style string-query. e.g. post_types=post,page&link_nofollow=1&exclude_post_ids=5,6","top-10"),value:attributes.other_attributes,onChange:changeOtherAttributes})))]},save:()=>null})}(window.wp.blocks,window.wp.i18n,window.wp.element,window.wp.components,window.wp.editor,window.wp.blockEditor,window.wp.serverSideRender);

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,516 @@
<?php
/**
* Query API: Top_Ten_Query class
*
* @package Top_Ten
* @subpackage Top_Ten_Query
* @since 3.0.0
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'Top_Ten_Query' ) ) :
/**
* Query API: Top_Ten_Query class.
*
* @since 3.0.0
*/
class Top_Ten_Query extends WP_Query {
/**
* Query vars, before parsing.
*
* @since 3.0.2
* @var int[]
*/
public $blog_id;
/**
* Cache set flag.
*
* @since 3.0.0
* @var bool
*/
public $in_cache = false;
/**
* Daily flag.
*
* @since 3.0.0
* @var bool
*/
public $is_daily = false;
/**
* Query vars, before parsing.
*
* @since 3.0.2
* @var array
*/
public $input_query_args = array();
/**
* Query vars, after parsing.
*
* @since 3.0.0
* @var array
*/
public $query_args = array();
/**
* Top Ten table name being queried.
*
* @since 3.0.0
* @var string
*/
public $table_name;
/**
* Main constructor.
*
* @since 3.0.0
*
* @param array|string $args The Query variables. Accepts an array or a query string.
*/
public function __construct( $args = array() ) {
$this->prepare_query_args( $args );
add_filter( 'posts_fields', array( $this, 'posts_fields' ), 10, 2 );
add_filter( 'posts_join', array( $this, 'posts_join' ), 10, 2 );
add_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 );
add_filter( 'posts_orderby', array( $this, 'posts_orderby' ), 10, 2 );
add_filter( 'posts_groupby', array( $this, 'posts_groupby' ), 10, 2 );
add_filter( 'posts_pre_query', array( $this, 'posts_pre_query' ), 10, 2 );
add_filter( 'the_posts', array( $this, 'the_posts' ), 10, 2 );
parent::__construct( $this->query_args );
// Remove filters after use.
remove_filter( 'posts_fields', array( $this, 'posts_fields' ) );
remove_filter( 'posts_join', array( $this, 'posts_join' ) );
remove_filter( 'posts_where', array( $this, 'posts_where' ) );
remove_filter( 'posts_orderby', array( $this, 'posts_orderby' ) );
remove_filter( 'posts_groupby', array( $this, 'posts_groupby' ) );
remove_filter( 'posts_pre_query', array( $this, 'posts_pre_query' ) );
remove_filter( 'the_posts', array( $this, 'the_posts' ) );
}
/**
* Prepare the query variables.
*
* @since 3.0.0
* @see WP_Query::parse_query()
* @see tptn_get_registered_settings()
*
* @param string|array $args {
* Optional. Array or string of Query parameters.
*
* @type array|string $blog_id An array or comma-separated string of blog IDs.
* @type bool $daily Set to true to get the daily/custom period posts. False for overall.
* @type array|string $include_cat_ids An array or comma-separated string of category/custom taxonomy term_taxonomy_ids.
* @type array|string $include_post_ids An array or comma-separated string of post IDs.
* @type bool $offset Offset the related posts returned by this number.
* @type bool $strict_limit If this is set to false, then it will fetch 3x posts.
* }
*/
public function prepare_query_args( $args = array() ) {
global $wpdb;
$tptn_settings = tptn_get_settings();
$defaults = array(
'blog_id' => get_current_blog_id(),
'daily' => false,
'include_cat_ids' => 0,
'include_post_ids' => 0,
'offset' => 0,
'strict_limit' => true,
);
$defaults = array_merge( $defaults, $tptn_settings );
$args = wp_parse_args( $args, $defaults );
// Set necessary variables.
$args['top_ten_query'] = true;
$args['suppress_filters'] = false;
$args['ignore_sticky_posts'] = true;
$args['no_found_rows'] = true;
// Store query args before we manipulate them.
$this->input_query_args = $args;
if ( $args['daily'] ) {
$this->table_name = $wpdb->base_prefix . 'top_ten_daily';
$this->is_daily = true;
} else {
$this->table_name = $wpdb->base_prefix . 'top_ten';
$this->is_daily = false;
}
// Set the number of posts to be retrieved.
$args['posts_per_page'] = ( $args['strict_limit'] ) ? $args['limit'] : ( $args['limit'] * 3 );
// If post_types is empty or contains a query string then use parse_str else consider it comma-separated.
if ( ! empty( $args['post_types'] ) && is_array( $args['post_types'] ) ) {
$post_types = $args['post_types'];
} elseif ( ! empty( $args['post_types'] ) && false === strpos( $args['post_types'], '=' ) ) {
$post_types = explode( ',', $args['post_types'] );
} else {
parse_str( $args['post_types'], $post_types ); // Save post types in $post_types variable.
}
// If post_types is empty or if we want all the post types.
if ( empty( $post_types ) || 'all' === $args['post_types'] ) {
$post_types = get_post_types(
array(
'public' => true,
)
);
}
/**
* Filter the post_types passed to the query.
*
* @since 2.2.0
* @since 3.0.0 Changed second argument from post ID to WP_Post object.
*
* @param array $post_types Array of post types to filter by.
* @param array $args Arguments array.
*/
$args['post_type'] = apply_filters( 'tptn_posts_post_types', $post_types, $args );
// Parse the blog_id argument to get an array of IDs.
$this->blog_id = wp_parse_id_list( $args['blog_id'] );
// Tax Query.
if ( ! empty( $args['tax_query'] ) && is_array( $args['tax_query'] ) ) {
$tax_query = $args['tax_query'];
} else {
$tax_query = array();
}
if ( ! empty( $args['include_cat_ids'] ) ) {
$tax_query[] = array(
'field' => 'term_taxonomy_id',
'terms' => wp_parse_id_list( $args['include_cat_ids'] ),
'include_children' => false,
);
}
if ( ! empty( $args['exclude_categories'] ) ) {
$tax_query[] = array(
'field' => 'term_taxonomy_id',
'terms' => wp_parse_id_list( $args['exclude_categories'] ),
'operator' => 'NOT IN',
'include_children' => false,
);
}
/**
* Filter the tax_query passed to the query.
*
* @since 3.0.0
*
* @param array $tax_query Array of tax_query parameters.
* @param array $args Arguments array.
*/
$tax_query = apply_filters( 'top_ten_query_tax_query', $tax_query, $args );
// Add a relation key if more than one $tax_query.
if ( count( $tax_query ) > 1 ) {
$tax_query['relation'] = 'AND';
}
$args['tax_query'] = $tax_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
// Set date_query.
$args['date_query'] = array(
array(
'after' => $args['how_old'] ? tptn_get_from_date( null, $args['how_old'] + 1, 0 ) : '',
'before' => current_time( 'mysql' ),
'inclusive' => true,
),
);
// Set post_status.
$args['post_status'] = empty( $args['post_status'] ) ? array( 'publish', 'inherit' ) : $args['post_status'];
// Set post__not_in for WP_Query using exclude_post_ids.
$exclude_post_ids = empty( $args['exclude_post_ids'] ) ? array() : wp_parse_id_list( $args['exclude_post_ids'] );
/**
* Filter exclude post IDs array.
*
* @since 2.2.0
* @since 3.0.0 Added $args
*
* @param int[] $exclude_post_ids Array of post IDs.
* @param array $args Arguments array.
*/
$exclude_post_ids = apply_filters( 'tptn_exclude_post_ids', $exclude_post_ids, $args );
$args['post__not_in'] = $exclude_post_ids;
// Unset what we don't need.
unset( $args['title'] );
unset( $args['title_daily'] );
unset( $args['blank_output'] );
unset( $args['blank_output_text'] );
unset( $args['show_excerpt'] );
unset( $args['excerpt_length'] );
unset( $args['show_date'] );
unset( $args['show_author'] );
unset( $args['disp_list_count'] );
unset( $args['title_length'] );
unset( $args['link_new_window'] );
unset( $args['link_nofollow'] );
unset( $args['before_list'] );
unset( $args['after_list'] );
unset( $args['before_list_item'] );
unset( $args['after_list_item'] );
/**
* Filters the arguments of the query.
*
* @since 3.0.0
*
* @param array $args The arguments of the query.
* @param Top_Ten_Query $this The Top_Ten_Query instance (passed by reference).
*/
$this->query_args = apply_filters_ref_array( 'top_ten_query_args', array( $args, &$this ) );
}
/**
* Modify the SELECT clause - posts_fields.
*
* @since 3.0.0
*
* @param string $fields The SELECT clause of the query.
* @param WP_Query $query The WP_Query instance.
* @return string Updated Fields
*/
public function posts_fields( $fields, $query ) {
global $wpdb;
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $fields;
}
$_fields[] = "{$this->table_name}.postnumber";
$_fields[] = $this->is_daily ? "SUM({$this->table_name}.cntaccess) as visits" : "{$this->table_name}.cntaccess as visits";
$_fields = implode( ', ', $_fields );
$fields .= ',' . $_fields;
return $fields;
}
/**
* Modify the posts_join clause.
*
* @since 3.0.0
*
* @param string $join The JOIN clause of the query.
* @param WP_Query $query The WP_Query instance.
* @return string Updated JOIN
*/
public function posts_join( $join, $query ) {
global $wpdb;
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $join;
}
$join .= " INNER JOIN {$this->table_name} ON {$this->table_name}.postnumber={$wpdb->posts}.ID ";
return $join;
}
/**
* Modify the posts_where clause.
*
* @since 3.0.0
*
* @param string $where The WHERE clause of the query.
* @param WP_Query $query The WP_Query instance.
* @return string Updated WHERE
*/
public function posts_where( $where, $query ) {
global $wpdb;
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $where;
}
$where .= " AND {$this->table_name}.blog_id IN ('" . join( "', '", $this->blog_id ) . "') "; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
if ( $this->is_daily ) {
if ( isset( $this->query_args['from_date'] ) ) {
$from_date = tptn_get_from_date( $this->query_args['from_date'], 0, 0 );
} else {
$from_date = tptn_get_from_date( null, $this->query_args['daily_range'], $this->query_args['hour_range'] );
}
$where .= $wpdb->prepare( " AND {$this->table_name}.dp_date >= %s ", $from_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
if ( isset( $this->query_args['to_date'] ) ) {
$to_date = tptn_get_from_date( $this->query_args['to_date'], 0, 0 );
$where .= $wpdb->prepare( " AND {$this->table_name}.dp_date <= %s ", $to_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
}
return $where;
}
/**
* Modify the posts_orderby clause.
*
* @since 3.0.0
*
* @param string $orderby The ORDER BY clause of the query.
* @param WP_Query $query The WP_Query instance.
* @return string Updated ORDER BY
*/
public function posts_orderby( $orderby, $query ) {
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $orderby;
}
// If orderby is set, then this was done intentionally and we don't make any modifications.
if ( ! empty( $query->get( 'orderby' ) ) ) {
return $orderby;
}
$orderby = ' visits DESC ';
return $orderby;
}
/**
* Modify the posts_groupby clause.
*
* @since 3.0.0
*
* @param string $groupby The GROUP BY clause of the query.
* @param WP_Query $query The WP_Query instance.
* @return string Updated GROUP BY
*/
public function posts_groupby( $groupby, $query ) {
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $groupby;
}
if ( $this->is_daily ) {
$groupby = " {$this->table_name}.postnumber ";
}
return $groupby;
}
/**
* Filter posts_pre_query to allow caching to work.
*
* @since 3.0.0
*
* @param string $posts Array of post data.
* @param WP_Query $query The WP_Query instance.
* @return string Updated Array of post objects.
*/
public function posts_pre_query( $posts, $query ) {
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $posts;
}
// Check the cache if there are any posts saved.
if ( ! empty( $this->query_args['cache_posts'] ) && ! ( is_preview() || is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) ) {
$cache_name = tptn_cache_get_key( $this->input_query_args );
$post_ids = get_transient( $cache_name );
if ( ! empty( $post_ids ) ) {
$posts = get_posts(
array(
'post__in' => $post_ids,
'fields' => $query->get( 'fields' ),
'orderby' => 'post__in',
'post_type' => $query->get( 'post_type' ),
)
);
$query->found_posts = count( $posts );
$query->max_num_pages = ceil( $query->found_posts / $query->get( 'posts_per_page' ) );
$this->in_cache = true;
}
}
return $posts;
}
/**
* Modify the array of retrieved posts.
*
* @since 3.0.0
*
* @param WP_Post[] $posts Array of post objects.
* @param WP_Query $query The WP_Query instance (passed by reference).
* @return string Updated Array of post objects.
*/
public function the_posts( $posts, $query ) {
// Return if it is not a Top_Ten_Query.
if ( true !== $query->get( 'top_ten_query' ) ) {
return $posts;
}
// Support caching to speed up retrieval.
if ( ! empty( $this->query_args['cache_posts'] ) && ! $this->in_cache && ! ( is_preview() || is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) ) {
/** This filter is defined in display-posts.php */
$cache_time = apply_filters( 'tptn_cache_time', $this->query_args['cache_time'], $this->query_args );
$cache_name = tptn_cache_get_key( $this->input_query_args );
$post_ids = wp_list_pluck( $query->posts, 'ID' );
set_transient( $cache_name, $post_ids, $cache_time );
}
if ( ! empty( $this->query_args['include_post_ids'] ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$include_post_ids = wp_parse_id_list( $this->query_args['include_post_ids'] );
}
if ( ! empty( $include_post_ids ) ) {
$extra_posts = get_posts(
array(
'post__in' => $include_post_ids,
'fields' => $query->get( 'fields' ),
'orderby' => 'post__in',
'post_type' => $query->get( 'post_type' ),
)
);
$posts = array_merge( $extra_posts, $posts );
}
// Shuffle posts if random order is set.
if ( $this->random_order ) {
shuffle( $posts );
}
/**
* Filter array of WP_Post objects before it is returned to the Top_Ten_Query instance.
*
* @since 3.0.0
*
* @param WP_Post[] $posts Array of post objects.
* @param array $args Arguments array.
*/
return apply_filters( 'top_ten_query_the_posts', $posts, $this->query_args );
}
}
endif;

View File

@@ -0,0 +1,338 @@
<?php
/**
* Functions controlling the counter/tracker
*
* @package Top_Ten
*/
/**
* Function to add the viewed count to the post content. Filters `the_content`.
*
* @since 1.0
* @param string $content Post content.
* @return string Filtered post content
*/
function tptn_pc_content( $content ) {
global $post;
$exclude_on_post_ids = explode( ',', tptn_get_option( 'exclude_on_post_ids' ) );
$add_to = tptn_get_option( 'add_to', false );
if ( isset( $post ) ) {
if ( in_array( $post->ID, $exclude_on_post_ids ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
return $content; // Exit without adding related posts.
}
}
if ( ( is_single() ) && ! empty( $add_to['single'] ) ) {
return $content . echo_tptn_post_count( 0 );
} elseif ( ( is_page() ) && ! empty( $add_to['page'] ) ) {
return $content . echo_tptn_post_count( 0 );
} elseif ( ( is_home() ) && ! empty( $add_to['home'] ) ) {
return $content . echo_tptn_post_count( 0 );
} elseif ( ( is_category() ) && ! empty( $add_to['category_archives'] ) ) {
return $content . echo_tptn_post_count( 0 );
} elseif ( ( is_tag() ) && ! empty( $add_to['tag_archives'] ) ) {
return $content . echo_tptn_post_count( 0 );
} elseif ( ( ( is_tax() ) || ( is_author() ) || ( is_date() ) ) && ! empty( $add_to['other_archives'] ) ) {
return $content . echo_tptn_post_count( 0 );
} else {
return $content;
}
}
add_filter( 'the_content', 'tptn_pc_content' );
/**
* Filter to display the post count when viewing feeds.
*
* @since 1.9.8
*
* @param string $content Post content.
* @return string Filtered post content
*/
function tptn_rss_filter( $content ) {
global $post;
$id = intval( $post->ID );
$add_to = tptn_get_option( 'add_to', false );
if ( ! empty( $add_to['feed'] ) ) {
return $content . '<div class="tptn_counter" id="tptn_counter_' . $id . '">' . get_tptn_post_count( $id ) . '</div>';
} else {
return $content;
}
}
add_filter( 'the_excerpt_rss', 'tptn_rss_filter' );
add_filter( 'the_content_feed', 'tptn_rss_filter' );
/**
* Function to manually display count.
*
* @since 1.0
* @param int|boolean $echo Flag to echo the output.
* @return string Formatted string if $echo is set to 0|false
*/
function echo_tptn_post_count( $echo = 1 ) {
global $post;
$home_url = home_url( '/' );
/**
* Filter the script URL of the counter.
*
* @since 2.0
*/
$home_url = apply_filters( 'tptn_view_counter_script_url', $home_url );
// Strip any query strings since we don't need them.
$home_url = strtok( $home_url, '?' );
$id = intval( $post->ID );
$nonce_action = 'tptn-nonce-' . $id;
$nonce = wp_create_nonce( $nonce_action );
if ( tptn_get_option( 'dynamic_post_count' ) ) {
$output = '<div class="tptn_counter" id="tptn_counter_' . $id . '"><script type="text/javascript" data-cfasync="false" src="' . $home_url . '?top_ten_id=' . $id . '&amp;view_counter=1&amp;_wpnonce=' . $nonce . '"></script></div>'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
} else {
$output = '<div class="tptn_counter" id="tptn_counter_' . $id . '">' . get_tptn_post_count( $id ) . '</div>';
}
/**
* Filter the viewed count script
*
* @since 2.0.0
*
* @param string $output Counter viewed count code
*/
$output = apply_filters( 'tptn_view_post_count', $output );
if ( $echo ) {
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
return $output;
}
}
/**
* Return the formatted post count for the supplied ID.
*
* @since 1.9.2
* @param int|string $id Post ID.
* @param int|string $blog_id Blog ID.
* @return int|string Formatted post count
*/
function get_tptn_post_count( $id = false, $blog_id = false ) {
$count_disp_form = stripslashes( tptn_get_option( 'count_disp_form' ) );
$count_disp_form_zero = stripslashes( tptn_get_option( 'count_disp_form_zero' ) );
$totalcntaccess = get_tptn_post_count_only( $id, 'total', $blog_id );
if ( $id > 0 ) {
// Total count per post.
if ( ( false !== strpos( $count_disp_form, '%totalcount%' ) ) || ( false !== strpos( $count_disp_form_zero, '%totalcount%' ) ) ) {
if ( ( 0 === (int) $totalcntaccess ) && ( ! is_singular() ) ) {
$count_disp_form_zero = str_replace( '%totalcount%', $totalcntaccess, $count_disp_form_zero );
} else {
$count_disp_form = str_replace( '%totalcount%', ( 0 === (int) $totalcntaccess ? $totalcntaccess + 1 : $totalcntaccess ), $count_disp_form );
}
}
// Now process daily count.
if ( ( false !== strpos( $count_disp_form, '%dailycount%' ) ) || ( false !== strpos( $count_disp_form_zero, '%dailycount%' ) ) ) {
$cntaccess = get_tptn_post_count_only( $id, 'daily' );
if ( ( 0 === (int) $totalcntaccess ) && ( ! is_singular() ) ) {
$count_disp_form_zero = str_replace( '%dailycount%', $cntaccess, $count_disp_form_zero );
} else {
$count_disp_form = str_replace( '%dailycount%', ( 0 === (int) $cntaccess ? $cntaccess + 1 : $cntaccess ), $count_disp_form );
}
}
// Now process overall count.
if ( ( false !== strpos( $count_disp_form, '%overallcount%' ) ) || ( false !== strpos( $count_disp_form_zero, '%overallcount%' ) ) ) {
$cntaccess = get_tptn_post_count_only( $id, 'overall' );
if ( ( 0 === (int) $cntaccess ) && ( ! is_singular() ) ) {
$count_disp_form_zero = str_replace( '%overallcount%', $cntaccess, $count_disp_form_zero );
} else {
$count_disp_form = str_replace( '%overallcount%', ( 0 === (int) $cntaccess ? $cntaccess + 1 : $cntaccess ), $count_disp_form );
}
}
if ( ( 0 === (int) $totalcntaccess ) && ( ! is_singular() ) ) {
return apply_filters( 'tptn_post_count', $count_disp_form_zero );
} else {
return apply_filters( 'tptn_post_count', $count_disp_form );
}
} else {
return 0;
}
}
/**
* Returns the post count.
*
* @since 1.9.8.5
*
* @param mixed $id Post ID.
* @param string $count Which count to return? total, daily or overall.
* @param bool $blog_id Blog ID.
* @return int Post count
*/
function get_tptn_post_count_only( $id = false, $count = 'total', $blog_id = false ) {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
if ( empty( $blog_id ) ) {
$blog_id = get_current_blog_id();
}
if ( $id > 0 ) {
switch ( $count ) {
case 'total':
$resultscount = $wpdb->get_row( $wpdb->prepare( "SELECT postnumber, cntaccess as visits FROM {$table_name} WHERE postnumber = %d AND blog_id = %d ", $id, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
break;
case 'daily':
$from_date = tptn_get_from_date();
$resultscount = $wpdb->get_row( $wpdb->prepare( "SELECT postnumber, SUM(cntaccess) as visits FROM {$table_name_daily} WHERE postnumber = %d AND blog_id = %d AND dp_date >= %s GROUP BY postnumber ", array( $id, $blog_id, $from_date ) ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
break;
case 'overall':
$resultscount = $wpdb->get_row( 'SELECT SUM(cntaccess) as visits FROM ' . $table_name ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
break;
}
$visits = ( $resultscount ) ? $resultscount->visits : 0;
$string = tptn_number_format_i18n( $visits );
/**
* Returns the post count.
*
* @since 2.6.0
*
* @param string $string Formatted post count.
* @param mixed $id Post ID.
* @param string $count Which count to return? total, daily or overall.
* @param bool $blog_id Blog ID.
*/
return apply_filters( 'tptn_post_count_only', $string, $id, $count, $blog_id );
} else {
return 0;
}
}
/**
* Delete post count.
*
* @since 2.9.0
*
* @param int $post_id Post ID.
* @param int $blog_id Blog ID.
* @param bool $daily Daily flag.
* @return bool|int Number of rows affected or false if error.
*/
function tptn_delete_count( $post_id, $blog_id, $daily = false ) {
global $wpdb;
$post_id = intval( $post_id );
$blog_id = intval( $blog_id );
if ( empty( $post_id ) || empty( $blog_id ) ) {
return false;
}
$table_name = $wpdb->base_prefix . 'top_ten';
if ( $daily ) {
$table_name .= '_daily';
}
$results = $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"DELETE FROM {$table_name} WHERE postnumber = %d AND blog_id = %d", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$post_id,
$blog_id
)
);
return $results;
}
/**
* Function to update the Top 10 count with ajax.
*
* @since 2.9.0
*/
function tptn_edit_count_ajax() {
if ( ! isset( $_REQUEST['total_count'] ) || ! isset( $_REQUEST['post_id'] ) || ! isset( $_REQUEST['total_count_original'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
wp_die( 0 );
}
$results = 0;
$post_id = intval( $_REQUEST['post_id'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$blog_id = get_current_blog_id();
$total_count = filter_var( $_REQUEST['total_count'], FILTER_SANITIZE_NUMBER_INT ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
$total_count_original = filter_var( $_REQUEST['total_count_original'], FILTER_SANITIZE_NUMBER_INT ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
// If our current user can't edit this post, bail.
if ( ! current_user_can( 'edit_post', $post_id ) ) {
wp_die( 0 );
}
if ( $total_count_original !== $total_count ) {
$results = tptn_edit_count( $post_id, $blog_id, $total_count );
}
echo wp_json_encode( $results );
wp_die();
}
add_action( 'wp_ajax_tptn_edit_count_ajax', 'tptn_edit_count_ajax' );
/**
* Function to edit the count.
*
* @since 2.9.0
*
* @param int $post_id Post ID.
* @param int $blog_id Blog ID.
* @param int $total_count Total count.
* @return bool|int Number of rows affected or false if error.
*/
function tptn_edit_count( $post_id, $blog_id, $total_count ) {
global $wpdb;
$post_id = intval( $post_id );
$blog_id = intval( $blog_id );
$total_count = intval( $total_count );
if ( empty( $post_id ) || empty( $blog_id ) || empty( $total_count ) ) {
return false;
}
$table_name = $wpdb->base_prefix . 'top_ten';
$results = $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"INSERT INTO {$table_name} (postnumber, cntaccess, blog_id) VALUES( %d, %d, %d ) ON DUPLICATE KEY UPDATE cntaccess= %d ", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$post_id,
$total_count,
$blog_id,
$total_count
)
);
return $results;
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* Cron functions
*
* @package Top_Ten
*/
/**
* Function to truncate daily run.
*
* @since 1.9.9.1
*/
function tptn_cron() {
global $wpdb;
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
$delete_from = TOP_TEN_STORE_DATA;
/**
* Override maintenance day range.
*
* @since 2.5.0
*
* @param int $delete_from Number of days before which post data is deleted from daily tables.
*/
$delete_from = apply_filters( 'tptn_maintenance_days', $delete_from );
$current_time = strtotime( current_time( 'mysql' ) );
$from_date = strtotime( "-{$delete_from} DAY", $current_time );
$from_date = gmdate( 'Y-m-d H', $from_date );
$resultscount = $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->prepare(
"DELETE FROM {$table_name_daily} WHERE dp_date <= %s ", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$from_date
)
);
}
add_action( 'tptn_cron_hook', 'tptn_cron' );
/**
* Function to enable run or actions.
*
* @since 1.9
* @param int $hour Hour.
* @param int $min Minute.
* @param int $recurrence Frequency.
*/
function tptn_enable_run( $hour, $min, $recurrence ) {
// Invoke WordPress internal cron.
if ( ! wp_next_scheduled( 'tptn_cron_hook' ) ) {
wp_schedule_event( mktime( $hour, $min, 0 ), $recurrence, 'tptn_cron_hook' );
} else {
wp_clear_scheduled_hook( 'tptn_cron_hook' );
wp_schedule_event( mktime( $hour, $min, 0 ), $recurrence, 'tptn_cron_hook' );
}
}
/**
* Function to disable daily run or actions.
*
* @since 1.9
*/
function tptn_disable_run() {
if ( wp_next_scheduled( 'tptn_cron_hook' ) ) {
wp_clear_scheduled_hook( 'tptn_cron_hook' );
}
}
// Let's declare this conditional function to add more schedules. It will be a generic function across all plugins that I develop.
if ( ! function_exists( 'ald_more_reccurences' ) ) :
/**
* Function to add weekly and fortnightly recurrences. Filters `cron_schedules`.
*
* @param array $schedules Array of existing schedules.
* @return array Filtered array with new schedules
*/
function ald_more_reccurences( $schedules ) {
// Add a 'weekly' interval.
$schedules['weekly'] = array(
'interval' => WEEK_IN_SECONDS,
'display' => __( 'Once Weekly', 'top-10' ),
);
$schedules['fortnightly'] = array(
'interval' => 2 * WEEK_IN_SECONDS,
'display' => __( 'Once Fortnightly', 'top-10' ),
);
$schedules['monthly'] = array(
'interval' => 30 * DAY_IN_SECONDS,
'display' => __( 'Once Monthly', 'top-10' ),
);
$schedules['quarterly'] = array(
'interval' => 90 * DAY_IN_SECONDS,
'display' => __( 'Once quarterly', 'top-10' ),
);
return $schedules;
}
add_filter( 'cron_schedules', 'ald_more_reccurences' );
endif;

View File

@@ -0,0 +1,360 @@
<?php
/**
* Deprecated functions and variables from Top 10. You shouldn't
* use these functions or variables and look for the alternatives instead.
* The functions will be removed in a later version.
*
* @package Top_Ten
*/
/**
* Holds the filesystem directory path (with trailing slash) for Top 10
*
* @since 1.5
* @deprecated 2.3
*
* @var string
*/
$tptn_path = plugin_dir_path( TOP_TEN_PLUGIN_FILE );
/**
* Holds the URL for Top 10
*
* @since 1.5
* @deprecated 2.3
*
* @var string
*/
$tptn_url = plugins_url() . '/' . plugin_basename( dirname( TOP_TEN_PLUGIN_FILE ) );
/**
* Filter to add related posts to feeds.
*
* @since 1.9.8
* @deprecated 2.2.0
*
* @param string $content Post content.
* @return string Filtered post content
*/
function ald_tptn_rss( $content ) {
_deprecated_function( __FUNCTION__, '2.2.0', 'tptn_rss_filter()' );
return tptn_rss_filter( $content );
}
/**
* Function to update the post views for the current post. Filters `the_content`.
*
* @since 1.0
*
* @deprecated 2.4.0
*
* @param string $content Post content.
*/
function tptn_add_viewed_count( $content = '' ) {
global $post, $tptn_settings;
_deprecated_function( __FUNCTION__, '2.4.0' );
$home_url = home_url( '/' );
$track_users = tptn_get_option( 'track_users' );
$trackers = tptn_get_option( 'trackers' );
/**
* Filter the script URL of the counter.
*
* @since 2.0
*/
$home_url = apply_filters( 'tptn_add_counter_script_url', $home_url );
// Strip any query strings since we don't need them.
$home_url = strtok( $home_url, '?' );
if ( is_singular() && 'draft' !== $post->post_status ) {
// Let's get the current user.
$current_user = wp_get_current_user();
// Is the current user the post author?
$post_author = ( $current_user->ID == $post->post_author ) ? true : false; // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
// Is the current user an admin?
$current_user_admin = ( current_user_can( 'manage_options' ) ) ? true : false;
// Is the current user an editor?
$current_user_editor = ( ( current_user_can( 'edit_others_posts' ) ) && ( ! current_user_can( 'manage_options' ) ) ) ? true : false;
$include_code = true;
if ( ( $post_author ) && ( empty( $track_users['authors'] ) ) ) {
$include_code = false;
}
if ( ( $current_user_admin ) && ( empty( $track_users['admins'] ) ) ) {
$include_code = false;
}
if ( ( $current_user_editor ) && ( empty( $track_users['editors'] ) ) ) {
$include_code = false;
}
if ( ( $current_user->exists() ) && ( ! tptn_get_option( 'logged_in' ) ) ) {
$include_code = false;
}
if ( $include_code ) {
$output = '';
$id = intval( $post->ID );
$blog_id = get_current_blog_id();
$activate_counter = ! empty( $trackers['overall'] ) ? 1 : 0; // It's 1 if we're updating the overall count.
$activate_counter = $activate_counter + ( ! empty( $trackers['daily'] ) ? 10 : 0 ); // It's 10 if we're updating the daily count.
if ( $activate_counter > 0 ) {
$output = '
<script type="text/javascript"> jQuery(document).ready(function() {
jQuery.ajax({
url: "' . $home_url . '",
data: {
top_ten_id: ' . $id . ',
top_ten_blog_id: ' . $blog_id . ',
activate_counter: ' . $activate_counter . ',
top10_rnd: (new Date()).getTime() + "-" + Math.floor(Math.random() * 100000)
}
});
});</script>';
}
/**
* Filter the counter script
*
* @since 1.9.8.5
*
* @param string $output Counter script code
*/
$output = apply_filters( 'tptn_viewed_count', $output );
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
}
/**
* Add tracker code.
*
* @since 2.3.0
*
* @deprecated 2.4.0
*
* @param bool $echo Echo the code or return it.
* @return string|void
*/
function tptn_add_tracker( $echo = true ) {
_deprecated_function( __FUNCTION__, '2.4.0' );
if ( $echo ) {
echo tptn_add_viewed_count( '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
return tptn_add_viewed_count( '' );
}
}
/**
* Default Options.
*
* @since 1.0
*
* @deprecated 2.5.0
*
* @return array
*/
function tptn_default_options() {
_deprecated_function( __FUNCTION__, '2.5.0' );
$title = __( '<h3>Popular Posts</h3>', 'top-10' );
$title_daily = __( '<h3>Daily Popular</h3>', 'top-10' );
$blank_output_text = __( 'No top posts yet', 'top-10' );
$thumb_default = plugins_url( 'default.png', __FILE__ );
// Get relevant post types.
$args = array(
'public' => true,
'_builtin' => true,
);
$post_types = http_build_query( get_post_types( $args ), '', '&' );
$tptn_settings = array(
/* General options */
'activate_daily' => true, // Activate the daily count.
'activate_overall' => true, // Activate overall count.
'cache' => false, // Enable Caching using Transienst API.
'cache_time' => HOUR_IN_SECONDS, // Cache for 1 Hour.
'daily_midnight' => true, // Start daily counts from midnight (default as old behaviour).
'daily_range' => '1', // Daily Popular will contain posts of how many days?
'hour_range' => '0', // Daily Popular will contain posts of how many hours?
'uninstall_clean_options' => true, // Cleanup options.
'uninstall_clean_tables' => false, // Cleanup tables.
'show_metabox' => true, // Show metabox to admins.
'show_metabox_admins' => false, // Limit to admins as well.
'show_credit' => false, // Add link to plugin page of my blog in top posts list.
/* Counter and tracker options */
'add_to_content' => true, // Add post count to content (only on single posts).
'count_on_pages' => true, // Add post count to pages.
'add_to_feed' => false, // Add post count to feed (full).
'add_to_home' => false, // Add post count to home page.
'add_to_category_archives' => false, // Add post count to category archives.
'add_to_tag_archives' => false, // Add post count to tag archives.
'add_to_archives' => false, // Add post count to other archives.
'count_disp_form' => '(Visited %totalcount% times, %dailycount% visits today)', // Format to display the count.
'count_disp_form_zero' => 'No visits yet', // What to display where there are no hits?
'dynamic_post_count' => false, // Use JavaScript for displaying the post count.
'tracker_type' => 'query_based', // Tracker type.
'track_authors' => false, // Track Authors visits.
'track_admins' => true, // Track Admin visits.
'track_editors' => true, // Track Admin visits.
'pv_in_admin' => true, // Add an extra column on edit posts/pages to display page views?
'show_count_non_admins' => true, // Show counts to non-admins.
/* Popular post list options */
'limit' => '10', // How many posts to display?
'how_old' => '0', // How old posts? Default is no limit.
'post_types' => $post_types, // WordPress custom post types.
'exclude_categories' => '', // Exclude these categories.
'exclude_cat_slugs' => '', // Exclude these categories (slugs).
'exclude_post_ids' => '', // Comma separated list of page / post IDs that are to be excluded in the results.
'title' => $title, // Title of Popular Posts.
'title_daily' => $title_daily, // Title of Daily Popular.
'blank_output' => false, // Blank output? Default is "blank Output test".
'blank_output_text' => $blank_output_text, // Blank output text.
'show_excerpt' => false, // Show description in list item.
'excerpt_length' => '10', // Length of characters.
'show_date' => false, // Show date in list item.
'show_author' => false, // Show author in list item.
'title_length' => '60', // Limit length of post title.
'disp_list_count' => true, // Display count in popular lists?
'link_new_window' => false, // Open links in new window.
'link_nofollow' => false, // Add no-follow to links.
'exclude_on_post_ids' => '', // Comma separate list of page/post IDs to not display related posts on.
// List HTML options.
'before_list' => '<ul>', // Before the entire list.
'after_list' => '</ul>', // After the entire list.
'before_list_item' => '<li>', // Before each list item.
'after_list_item' => '</li>', // After each list item.
/* Thumbnail options */
'post_thumb_op' => 'text_only', // Display only text in posts.
'thumb_size' => 'tptn_thumbnail', // Default thumbnail size.
'thumb_width' => '150', // Max width of thumbnails.
'thumb_height' => '150', // Max height of thumbnails.
'thumb_crop' => true, // Crop mode. default is hard crop.
'thumb_html' => 'html', // Use HTML or CSS for width and height of the thumbnail?
'thumb_meta' => 'post-image', // Meta field that is used to store the location of default thumbnail image.
'scan_images' => true, // Scan post for images.
'thumb_default' => $thumb_default, // Default thumbnail image.
'thumb_default_show' => true, // Show default thumb if none found (if false, don't show thumb at all).
/* Custom styles */
'custom_css' => '', // Custom CSS to style the output.
'include_default_style' => false, // Include default Top 10 style.
'tptn_styles' => 'no_style', // Defaault style is left thubnails.
/* Maintenance cron */
'cron_on' => false, // Run cron daily?
'cron_hour' => '0', // Cron Hour.
'cron_min' => '0', // Cron Minute.
'cron_recurrence' => 'weekly', // Frequency of cron.
);
/**
* Filters the default options array.
*
* @since 1.9.10.1
*
* @param array $tptn_settings Default options
*/
return apply_filters( 'tptn_default_options', $tptn_settings );
}
/**
* Function to read options from the database.
*
* @since 1.0
*
* @deprecated 2.5.0
*
* @return array
*/
function tptn_read_options() {
_deprecated_function( __FUNCTION__, '2.5.0', 'tptn_get_settings()' );
$tptn_settings_changed = false;
$defaults = tptn_default_options();
$tptn_settings = array_map( 'stripslashes', (array) get_option( 'ald_tptn_settings' ) );
unset( $tptn_settings[0] ); // Produced by the (array) casting when there's nothing in the DB.
foreach ( $defaults as $k => $v ) {
if ( ! isset( $tptn_settings[ $k ] ) ) {
$tptn_settings[ $k ] = $v;
$tptn_settings_changed = true;
}
}
if ( true === $tptn_settings_changed ) {
update_option( 'ald_tptn_settings', $tptn_settings );
}
/**
* Filters the options array.
*
* @since 1.9.10.1
*
* @param array $tptn_settings Options read from the database
*/
return apply_filters( 'tptn_read_options', $tptn_settings );
}
/**
* Function to limit content by characters.
*
* @since 1.9.8
*
* @deprecated 2.5.4
*
* @param string $content Content to be used to make an excerpt.
* @param int $no_of_char Maximum length of excerpt in characters.
* @return string Formatted content.
*/
function tptn_max_formatted_content( $content, $no_of_char = -1 ) {
_deprecated_function( __FUNCTION__, '2.5.4', 'tptn_trim_char()' );
$content = tptn_trim_char( $content, $no_of_char );
/**
* Filters formatted content after cropping.
*
* @since 1.9.10.1
*
* @param string $content Formatted content
* @param int $no_of_char Maximum length of excerpt in characters
*/
return apply_filters( 'tptn_max_formatted_content', $content, $no_of_char );
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* Language functions
*
* @package Top_Ten
*/
/**
* Function to create an excerpt for the post.
*
* @since 1.6
* @param int $id Post ID.
* @param int|string $excerpt_length Length of the excerpt in words.
* @param bool $use_excerpt Use Excerpt.
* @return string Excerpt
*/
function tptn_excerpt( $id, $excerpt_length = 0, $use_excerpt = true ) {
$content = '';
$post = get_post( $id );
if ( empty( $post ) ) {
return '';
}
if ( $use_excerpt ) {
$content = $post->post_excerpt;
}
if ( empty( $content ) ) {
$content = $post->post_content;
}
$output = wp_strip_all_tags( strip_shortcodes( $content ) );
if ( $excerpt_length > 0 ) {
$output = wp_trim_words( $output, $excerpt_length );
}
if ( post_password_required( $post ) ) {
$output = __( 'There is no excerpt because this is a protected post.', 'top-10' );
}
/**
* Filters excerpt generated by tptn.
*
* @since 1.9.10.1
*
* @param array $output Formatted excerpt
* @param int $id Post ID
* @param int $excerpt_length Length of the excerpt
* @param boolean $use_excerpt Use the excerpt?
*/
return apply_filters( 'tptn_excerpt', $output, $id, $excerpt_length, $use_excerpt );
}
/**
* Truncate a string to a certain length.
*
* @since 2.5.4
*
* @param string $string String to truncate.
* @param int $count Maximum number of characters to take.
* @param string $more What to append if $string needs to be trimmed.
* @param bool $break_words Optionally choose to break words.
* @return string Truncated string.
*/
function tptn_trim_char( $string, $count = 60, $more = '&hellip;', $break_words = false ) {
$string = wp_strip_all_tags( $string, true );
if ( 0 === $count ) {
return '';
}
if ( mb_strlen( $string ) > $count && $count > 0 ) {
$count -= min( $count, mb_strlen( $more ) );
if ( ! $break_words ) {
$string = preg_replace( '/\s+?(\S+)?$/u', '', mb_substr( $string, 0, $count + 1 ) );
}
$string = mb_substr( $string, 0, $count ) . $more;
}
/**
* Filters truncated string.
*
* @since 2.4.0
*
* @param string $string String to truncate.
* @param int $count Maximum number of characters to take.
* @param string $more What to append if $string needs to be trimmed.
* @param bool $break_words Optionally choose to break words.
*/
return apply_filters( 'tptn_trim_char', $string, $count, $more, $break_words );
}

View File

@@ -0,0 +1,152 @@
<?php
/**
* Helper functions
*
* @package Top_Ten
*/
/**
* Function to delete all rows in the posts table.
*
* @since 1.3
* @param bool $daily Daily flag.
*/
function tptn_trunc_count( $daily = true ) {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
if ( $daily ) {
$table_name .= '_daily';
}
$sql = "TRUNCATE TABLE $table_name";
$wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
}
/**
* Retrieve the from date for the query
*
* @since 2.6.0
*
* @param string $time A date/time string.
* @param int $daily_range Daily range.
* @param int $hour_range Hour range.
* @return string From date
*/
function tptn_get_from_date( $time = null, $daily_range = null, $hour_range = null ) {
$current_time = isset( $time ) ? strtotime( $time ) : strtotime( current_time( 'mysql' ) );
$daily_range = isset( $daily_range ) ? $daily_range : tptn_get_option( 'daily_range' );
$hour_range = isset( $hour_range ) ? $hour_range : tptn_get_option( 'hour_range' );
if ( tptn_get_option( 'daily_midnight' ) ) {
$from_date = $current_time - ( max( 0, ( $daily_range - 1 ) ) * DAY_IN_SECONDS );
$from_date = gmdate( 'Y-m-d 0:0:0', $from_date );
} else {
$from_date = $current_time - ( $daily_range * DAY_IN_SECONDS + $hour_range * HOUR_IN_SECONDS );
$from_date = gmdate( 'Y-m-d H:0:0', $from_date );
}
/**
* Retrieve the from date for the query
*
* @since 2.6.0
*
* @param string $from_date From date.
* @param string $time A date/time string.
* @param int $daily_range Daily range.
* @param int $hour_range Hour range.
*/
return apply_filters( 'tptn_get_from_date', $from_date, $time, $daily_range, $hour_range );
}
/**
* Convert float number to format based on the locale if number_format_count is true.
*
* @since 2.6.0
*
* @param float $number The number to convert based on locale.
* @param int $decimals Optional. Precision of the number of decimal places. Default 0.
* @return string Converted number in string format.
*/
function tptn_number_format_i18n( $number, $decimals = 0 ) {
$formatted = $number;
if ( tptn_get_option( 'number_format_count' ) ) {
$formatted = number_format_i18n( $number );
}
/**
* Filters the number formatted based on the locale.
*
* @since 2.6.0
*
* @param string $formatted Converted number in string format.
* @param float $number The number to convert based on locale.
* @param int $decimals Precision of the number of decimal places.
*/
return apply_filters( 'number_format_i18n', $formatted, $number, $decimals );
}
/**
* Convert a string to CSV.
*
* @since 2.9.0
*
* @param array $array Input string.
* @param string $delimiter Delimiter.
* @param string $enclosure Enclosure.
* @param string $terminator Terminating string.
* @return string CSV string.
*/
function tptn_str_putcsv( $array, $delimiter = ',', $enclosure = '"', $terminator = "\n" ) {
// First convert associative array to numeric indexed array.
$work_array = array();
foreach ( $array as $key => $value ) {
$work_array[] = $value;
}
$string = '';
$array_size = count( $work_array );
for ( $i = 0; $i < $array_size; $i++ ) {
// Nested array, process nest item.
if ( is_array( $work_array[ $i ] ) ) {
$string .= tptn_str_putcsv( $work_array[ $i ], $delimiter, $enclosure, $terminator );
} else {
switch ( gettype( $work_array[ $i ] ) ) {
// Manually set some strings.
case 'NULL':
$sp_format = '';
break;
case 'boolean':
$sp_format = ( true === $work_array[ $i ] ) ? 'true' : 'false';
break;
// Make sure sprintf has a good datatype to work with.
case 'integer':
$sp_format = '%i';
break;
case 'double':
$sp_format = '%0.2f';
break;
case 'string':
$sp_format = '%s';
$work_array[ $i ] = str_replace( "$enclosure", "$enclosure$enclosure", $work_array[ $i ] );
break;
// Unknown or invalid items for a csv - note: the datatype of array is already handled above, assuming the data is nested.
case 'object':
case 'resource':
default:
$sp_format = '';
break;
}
$string .= sprintf( '%2$s' . $sp_format . '%2$s', $work_array[ $i ], $enclosure );
$string .= ( $i < ( $array_size - 1 ) ) ? $delimiter : $terminator;
}
}
return $string;
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,9 @@
jQuery(document).ready(function($) {
$.post(ajax_tptn_tracker.ajax_url, {
action: 'tptn_tracker',
top_ten_id: ajax_tptn_tracker.top_ten_id,
top_ten_blog_id: ajax_tptn_tracker.top_ten_blog_id,
activate_counter: ajax_tptn_tracker.activate_counter,
top_ten_debug: ajax_tptn_tracker.top_ten_debug
});
});

View File

@@ -0,0 +1 @@
jQuery(document).ready((function($){$.post(ajax_tptn_tracker.ajax_url,{action:"tptn_tracker",top_ten_id:ajax_tptn_tracker.top_ten_id,top_ten_blog_id:ajax_tptn_tracker.top_ten_blog_id,activate_counter:ajax_tptn_tracker.activate_counter,top_ten_debug:ajax_tptn_tracker.top_ten_debug})}));

View File

@@ -0,0 +1,58 @@
<?php
/**
* Language functions
*
* @package Top_Ten
*/
/**
* Function to load translation files.
*
* @since 1.9.10.1
*/
function tptn_lang_init() {
load_plugin_textdomain( 'top-10', false, dirname( plugin_basename( TOP_TEN_PLUGIN_FILE ) ) . '/languages/' );
}
add_action( 'plugins_loaded', 'tptn_lang_init' );
/**
* Fetch the post of the correct language.
*
* @since 2.1.0
*
* @param int $post_id Post ID.
*/
function tptn_object_id_cur_lang( $post_id ) {
$return_original_if_missing = false;
/**
* Filter to modify if the original language ID is returned.
*
* @since 2.2.3
*
* @param bool $return_original_if_missing
* @param int $post_id Post ID
*/
$return_original_if_missing = apply_filters( 'tptn_wpml_return_original', $return_original_if_missing, $post_id );
if ( function_exists( 'pll_get_post' ) ) {
$post_id = pll_get_post( $post_id );
} elseif ( function_exists( 'wpml_object_id' ) ) {
$post_id = apply_filters( 'wpml_object_id', $post_id, get_post_type( $post_id ), $return_original_if_missing );
} elseif ( function_exists( 'icl_object_id' ) ) {
$post_id = icl_object_id( $post_id, get_post_type( $post_id ), $return_original_if_missing );
}
/**
* Filters object ID for current language (WPML).
*
* @since 2.1.0
*
* @param int $post_id Post ID
*/
return apply_filters( 'tptn_object_id_cur_lang', $post_id );
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* Widget to display the overall count.
*
* @package Top_Ten
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Widget to display the overall count.
*
* @extends WP_Widget
*/
class Top_Ten_Count_Widget extends WP_Widget {
/**
* Register widget with WordPress.
*/
public function __construct() {
parent::__construct(
'widget_tptn_count', // Base ID.
__( 'Overall count [Top 10]', 'top-10' ), // Name.
array(
'description' => __( 'Display overall count', 'where-did-they-go-from-here' ),
'customize_selective_refresh' => true,
'classname' => 'tptn_posts_count_widget',
)
);
}
/**
* Back-end widget form.
*
* @see WP_Widget::form()
*
* @param array $instance Previously saved values from database.
*/
public function form( $instance ) {
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php esc_html_e( 'Title', 'top-10' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</label>
</p>
<?php
/**
* Fires after Top 10 widget options.
*
* @since 2.0.0
*
* @param array $instance Widget options array
*/
do_action( 'tptn_widget_options_after', $instance );
?>
<?php
} //ending form creation
/**
* Sanitize widget form values as they are saved.
*
* @see WP_Widget::update()
*
* @param array $new_instance Values just sent to be saved.
* @param array $old_instance Previously saved values from database.
*
* @return array Updated safe values to be saved.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = wp_strip_all_tags( $new_instance['title'] );
/**
* Filters Update widget options array.
*
* @since 2.0.0
*
* @param array $instance Widget options array
*/
return apply_filters( 'tptn_widget_options_update', $instance );
} //ending update
/**
* Front-end display of widget.
*
* @see WP_Widget::widget()
*
* @param array $args Widget arguments.
* @param array $instance Saved values from database.
*/
public function widget( $args, $instance ) {
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? '' : $instance['title'] );
$output = $args['before_widget'];
$output .= $args['before_title'] . $title . $args['after_title'];
$output .= get_tptn_post_count_only( 1, 'overall', 0 );
$output .= $args['after_widget'];
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} //ending function widget
}
/**
* Initialise the widget.
*/
function tptn_register_count_widget() {
register_widget( 'Top_Ten_Count_Widget' );
}
add_action( 'widgets_init', 'tptn_register_count_widget', 1 );

View File

@@ -0,0 +1,334 @@
<?php
/**
* This class adds REST routes to update the count and return the list of popular posts.
*
* @package Top_Ten
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Query API: Top_Ten_Query class.
*
* @since 3.0.0
*/
class Top_Ten_REST_API extends \WP_REST_Controller {
/**
* Main constructor.
*
* @since 3.0.0
*/
public function __construct() {
$this->namespace = 'top-10/v1';
$this->posts_route = 'popular-posts';
$this->tracker_route = 'tracker';
}
/**
* Initialises the Top 10 REST API adding the necessary routes.
*
* @since 3.0.0
*/
public function register_routes() {
register_rest_route(
$this->namespace,
'/' . $this->posts_route,
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'permissions_check' ),
'args' => $this->get_items_params(),
)
);
register_rest_route(
$this->namespace,
'/' . $this->posts_route . '/(?P<id>[\d]+)',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
'permission_callback' => array( $this, 'permissions_check' ),
'args' => array(
'id' => array(
'description' => __( 'Post ID.', 'top-10' ),
'type' => 'integer',
),
),
)
);
register_rest_route(
$this->namespace,
'/' . $this->tracker_route,
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'update_post_count' ),
'permission_callback' => array( $this, 'permissions_check' ),
'args' => $this->get_tracker_params(),
)
);
}
/**
* Check if a given request has access to get items
*
* @param WP_REST_Request $request Full data about the request.
*
* @return WP_Error|bool
*/
public function permissions_check( $request ) {
return apply_filters( 'top_ten_rest_api_permissions_check', true, $request );
}
/**
* Get popular posts.
*
* @since 3.0.0
*
* @param WP_REST_Request $request WP Rest request.
* @return mixed|\WP_REST_Response Array of post objects or post IDs.
*/
public function get_items( $request ) {
$popular_posts = array();
$args = $request->get_params();
/**
* Filter the REST API arguments before they passed to get_tptn_posts().
*
* @since 3.0.0
*
* @param array $args Arguments array.
* @param WP_REST_Request $request WP Rest request.
*/
$args = apply_filters( 'top_ten_rest_api_get_tptn_posts_args', $args, $request );
$results = get_tptn_posts( $args );
if ( is_array( $results ) && ! empty( $results ) ) {
foreach ( $results as $popular_post ) {
if ( ! $this->check_read_permission( $popular_post ) ) {
continue;
}
$popular_posts[] = $this->prepare_item( $popular_post, $request );
}
}
return rest_ensure_response( $popular_posts );
}
/**
* Get a popular post by ID. Also includes the number of views.
*
* @since 3.0.0
*
* @param WP_REST_Request $request WP Rest request.
* @return mixed|\WP_REST_Response Array of post objects or post IDs.
*/
public function get_item( $request ) {
$id = $request->get_param( 'id' );
$error = new WP_Error(
'rest_post_invalid_id',
__( 'Invalid post ID.', 'top-10' ),
array( 'status' => 404 )
);
if ( (int) $id <= 0 ) {
return $error;
}
$post = get_post( (int) $id );
if ( empty( $post ) || empty( $post->ID ) || ! $this->check_read_permission( $post ) ) {
return $error;
}
$post = $this->prepare_item( $post, $request );
return rest_ensure_response( $post );
}
/**
* Get a popular post by ID. Also includes the number of views.
*
* @since 3.0.0
*
* @param WP_Post $popular_post Popular Post object.
* @param WP_REST_Request $request WP Rest request.
* @return array|mixed The formatted Popular Post object.
*/
public function prepare_item( $popular_post, $request ) {
// Need to prepare items for the rest response.
$posts_controller = new \WP_REST_Posts_Controller( $popular_post->post_type, $request );
$data = $posts_controller->prepare_item_for_response( $popular_post, $request );
// Add pageviews from popular_post object to response.
$visits = isset( $popular_post->visits ) ? $popular_post->visits : get_tptn_post_count_only( $popular_post->ID );
$data->data['visits'] = absint( $visits );
return $this->prepare_response_for_collection( $data );
}
/**
* Update post count.
*
* @since 3.0.0
*
* @param WP_REST_Request $request WP Rest request.
* @return mixed|\WP_REST_Response Array of post objects or post IDs.
*/
public function update_post_count( $request ) {
$id = absint( $request->get_param( 'top_ten_id' ) );
$blog_id = absint( $request->get_param( 'top_ten_blog_id' ) );
$activate_counter = absint( $request->get_param( 'activate_counter' ) );
$top_ten_debug = absint( $request->get_param( 'top_ten_debug' ) );
$str = tptn_update_count( $id, $blog_id, $activate_counter );
if ( 1 === $top_ten_debug ) {
return rest_ensure_response( $str );
} else {
$response = new \WP_REST_Response( '', 204 );
$response->header( 'Cache-Control', 'max-age=15, s-maxage=0' );
return $response;
}
}
/**
* Get the arguments for fetching the popular posts.
*
* @since 3.0.0
*
* @return array Top 10 REST API popular posts arguments.
*/
public function get_items_params() {
$args = array(
'limit' => array(
'description' => esc_html__( 'Number of posts', 'top-10' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
),
'post_types' => array(
'description' => esc_html__( 'Post types', 'top-10' ),
'type' => 'string',
),
);
return apply_filters( 'top_ten_rest_api_get_items_params', $args );
}
/**
* Get the arguments for tracking posts.
*
* @since 3.0.0
*
* @return array Top 10 REST API popular posts arguments.
*/
public function get_tracker_params() {
$args = array(
'top_ten_id' => array(
'description' => esc_html__( 'ID of the post.', 'top-10' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
),
'top_ten_blog_id' => array(
'description' => esc_html__( 'Blog ID of the post.', 'top-10' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
),
'activate_counter' => array(
'description' => esc_html__( 'Activate counter flag.', 'top-10' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
),
'top_ten_debug' => array(
'description' => esc_html__( 'Debug flag.', 'top-10' ),
'type' => 'integer',
'sanitize_callback' => 'absint',
),
);
return apply_filters( 'top_ten_rest_api_get_tracker_params', $args );
}
/**
* Checks if a given post type can be viewed or managed.
*
* @since 3.0.0
*
* @param WP_Post_Type|string $post_type Post type name or object.
* @return bool Whether the post type is allowed in REST.
*/
protected function check_is_post_type_allowed( $post_type ) {
if ( ! is_object( $post_type ) ) {
$post_type = get_post_type_object( $post_type );
}
if ( ! empty( $post_type ) && ! empty( $post_type->show_in_rest ) ) {
return true;
}
return false;
}
/**
* Checks if a post can be read.
*
* Correctly handles posts with the inherit status.
*
* @since 3.0.0
*
* @param WP_Post $post Post object.
* @return bool Whether the post can be read.
*/
public function check_read_permission( $post ) {
$post_type = get_post_type_object( $post->post_type );
if ( ! $this->check_is_post_type_allowed( $post_type ) ) {
return false;
}
// Is the post readable?
if ( 'publish' === $post->post_status || current_user_can( 'read_post', $post->ID ) ) {
return true;
}
$post_status_obj = get_post_status_object( $post->post_status );
if ( $post_status_obj && $post_status_obj->public ) {
return true;
}
// Can we read the parent if we're inheriting?
if ( 'inherit' === $post->post_status && $post->post_parent > 0 ) {
$parent = get_post( $post->post_parent );
if ( $parent ) {
return $this->check_read_permission( $parent );
}
}
/*
* If there isn't a parent, but the status is set to inherit, assume
* it's published (as per get_post_status()).
*/
if ( 'inherit' === $post->post_status ) {
return true;
}
return false;
}
}
/**
* Function to register our new routes from the controller.
*
* @since 3.0.0
*/
function tptn_register_rest_routes() {
$controller = new Top_Ten_REST_API();
$controller->register_routes();
}
add_action( 'rest_api_init', 'tptn_register_rest_routes' );

View File

@@ -0,0 +1,387 @@
<?php
/**
* Widget class.
*
* @package Top_Ten
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Top 10 Widget.
*
* @extends WP_Widget
*/
class Top_Ten_Widget extends WP_Widget {
/**
* Register widget with WordPress.
*/
public function __construct() {
parent::__construct(
'widget_tptn_pop', // Base ID.
__( 'Popular Posts [Top 10]', 'top-10' ), // Name.
array(
'description' => __( 'Display popular posts', 'where-did-they-go-from-here' ),
'customize_selective_refresh' => true,
'classname' => 'tptn_posts_list_widget',
)
);
add_action( 'wp_enqueue_scripts', array( $this, 'front_end_styles' ) );
}
/**
* Back-end widget form.
*
* @see WP_Widget::form()
*
* @param array $instance Previously saved values from database.
*/
public function form( $instance ) {
$title = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
$limit = isset( $instance['limit'] ) ? esc_attr( $instance['limit'] ) : '';
$offset = isset( $instance['offset'] ) ? esc_attr( $instance['offset'] ) : '';
$disp_list_count = isset( $instance['disp_list_count'] ) ? esc_attr( $instance['disp_list_count'] ) : '';
$show_excerpt = isset( $instance['show_excerpt'] ) ? esc_attr( $instance['show_excerpt'] ) : '';
$show_author = isset( $instance['show_author'] ) ? esc_attr( $instance['show_author'] ) : '';
$show_date = isset( $instance['show_date'] ) ? esc_attr( $instance['show_date'] ) : '';
$post_thumb_op = isset( $instance['post_thumb_op'] ) ? esc_attr( $instance['post_thumb_op'] ) : 'text_only';
$thumb_height = isset( $instance['thumb_height'] ) ? esc_attr( $instance['thumb_height'] ) : '';
$thumb_width = isset( $instance['thumb_width'] ) ? esc_attr( $instance['thumb_width'] ) : '';
$daily = isset( $instance['daily'] ) ? esc_attr( $instance['daily'] ) : 'overall';
$daily_range = isset( $instance['daily_range'] ) ? esc_attr( $instance['daily_range'] ) : '';
$hour_range = isset( $instance['hour_range'] ) ? esc_attr( $instance['hour_range'] ) : '';
$include_categories = isset( $instance['include_categories'] ) ? esc_attr( $instance['include_categories'] ) : '';
$include_cat_ids = isset( $instance['include_cat_ids'] ) ? esc_attr( $instance['include_cat_ids'] ) : '';
$include_post_ids = isset( $instance['include_post_ids'] ) ? esc_attr( $instance['include_post_ids'] ) : '';
// Parse the Post types.
$post_types = array();
if ( isset( $instance['post_types'] ) ) {
$post_types = $instance['post_types'];
parse_str( $post_types, $post_types ); // Save post types in $post_types variable.
}
$wp_post_types = get_post_types(
array(
'public' => true,
)
);
$posts_types_inc = array_intersect( $wp_post_types, $post_types );
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php esc_html_e( 'Title', 'top-10' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>">
<?php esc_html_e( 'No. of posts', 'top-10' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'limit' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'limit' ) ); ?>" type="text" value="<?php echo esc_attr( $limit ); ?>" />
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'offset' ) ); ?>">
<?php esc_html_e( 'Offset', 'top-10' ); ?>: <input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'offset' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'offset' ) ); ?>" type="text" value="<?php echo esc_attr( $offset ); ?>" />
</label>
</p>
<p>
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'daily' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'daily' ) ); ?>">
<option value="overall" <?php selected( 'overall', $daily, true ); ?>><?php esc_html_e( 'Overall', 'top-10' ); ?></option>
<option value="daily" <?php selected( 'daily', $daily, true ); ?>><?php esc_html_e( 'Custom time period (Enter below)', 'top-10' ); ?></option>
</select>
</p>
<p>
<?php esc_html_e( 'In days and hours (applies only to custom option above)', 'top-10' ); ?>:
<label for="<?php echo esc_attr( $this->get_field_id( 'daily_range' ) ); ?>">
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'daily_range' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'daily_range' ) ); ?>" type="text" value="<?php echo esc_attr( $daily_range ); ?>" /> <?php esc_html_e( 'days', 'top-10' ); ?>
</label>
<label for="<?php echo esc_attr( $this->get_field_id( 'hour_range' ) ); ?>">
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'hour_range' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'hour_range' ) ); ?>" type="text" value="<?php echo esc_attr( $hour_range ); ?>" /> <?php esc_html_e( 'hours', 'top-10' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'disp_list_count' ) ); ?>">
<input id="<?php echo esc_attr( $this->get_field_id( 'disp_list_count' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'disp_list_count' ) ); ?>" type="checkbox" <?php checked( true, $disp_list_count, true ); ?> /> <?php esc_html_e( 'Show count?', 'top-10' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'show_excerpt' ) ); ?>">
<input id="<?php echo esc_attr( $this->get_field_id( 'show_excerpt' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_excerpt' ) ); ?>" type="checkbox" <?php checked( true, $show_excerpt, true ); ?> /> <?php esc_html_e( 'Show excerpt?', 'top-10' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'show_author' ) ); ?>">
<input id="<?php echo esc_attr( $this->get_field_id( 'show_author' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_author' ) ); ?>" type="checkbox" <?php checked( true, $show_author, true ); ?> /> <?php esc_html_e( 'Show author?', 'top-10' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'show_date' ) ); ?>">
<input id="<?php echo esc_attr( $this->get_field_id( 'show_date' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_date' ) ); ?>" type="checkbox" <?php checked( true, $show_date, true ); ?> /> <?php esc_html_e( 'Show date?', 'top-10' ); ?>
</label>
</p>
<p>
<?php esc_html_e( 'Thumbnail options', 'top-10' ); ?>: <br />
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'post_thumb_op' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'post_thumb_op' ) ); ?>">
<option value="inline" <?php selected( 'inline', $post_thumb_op, true ); ?>><?php esc_html_e( 'Thumbnails inline, before title', 'top-10' ); ?></option>
<option value="after" <?php selected( 'after', $post_thumb_op, true ); ?>><?php esc_html_e( 'Thumbnails inline, after title', 'top-10' ); ?></option>
<option value="thumbs_only" <?php selected( 'thumbs_only', $post_thumb_op, true ); ?>><?php esc_html_e( 'Only thumbnails, no text', 'top-10' ); ?></option>
<option value="text_only" <?php selected( 'text_only', $post_thumb_op, true ); ?>><?php esc_html_e( 'No thumbnails, only text.', 'top-10' ); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'thumb_height' ) ); ?>">
<?php esc_html_e( 'Thumbnail height', 'top-10' ); ?>:
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'thumb_height' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'thumb_height' ) ); ?>" type="text" value="<?php echo esc_attr( $thumb_height ); ?>" />
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'thumb_width' ) ); ?>">
<?php esc_html_e( 'Thumbnail width', 'top-10' ); ?>:
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'thumb_width' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'thumb_width' ) ); ?>" type="text" value="<?php echo esc_attr( $thumb_width ); ?>" />
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'include_categories' ) ); ?>">
<?php esc_html_e( 'Only from categories', 'top-10' ); ?>:
<input class="widefat category_autocomplete" id="<?php echo esc_attr( $this->get_field_id( 'include_categories' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'include_categories' ) ); ?>" type="text" value="<?php echo esc_attr( $include_categories ); ?>" />
</label>
<input type="hidden" id="<?php echo esc_attr( $this->get_field_id( 'include_cat_ids' ) ); ?>" name="<?php echo esc_attr( $this->get_field_id( 'include_cat_ids' ) ); ?>" value="<?php echo esc_attr( $include_cat_ids ); ?>" />
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'include_post_ids' ) ); ?>">
<?php esc_html_e( 'Include IDs', 'top-10' ); ?>:
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'include_post_ids' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'include_post_ids' ) ); ?>" type="text" value="<?php echo esc_attr( $include_post_ids ); ?>" />
</label>
</p>
<p><?php esc_html_e( 'Post types to include:', 'top-10' ); ?><br />
<?php foreach ( $wp_post_types as $wp_post_type ) { ?>
<label>
<input id="<?php echo esc_attr( $this->get_field_id( 'post_types' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'post_types' ) ); ?>[]" type="checkbox" value="<?php echo esc_attr( $wp_post_type ); ?>" <?php checked( true, in_array( $wp_post_type, $posts_types_inc, true ), true ); ?> />
<?php echo esc_attr( $wp_post_type ); ?>
</label>
<br />
<?php } ?>
</p>
<?php
/**
* Fires after Top 10 widget options.
*
* @since 2.0.0
*
* @param array $instance Widget options array
*/
do_action( 'tptn_widget_options_after', $instance );
?>
<?php
}
/**
* Sanitize widget form values as they are saved.
*
* @see WP_Widget::update()
*
* @param array $new_instance Values just sent to be saved.
* @param array $old_instance Previously saved values from database.
*
* @return array Updated safe values to be saved.
*/
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = wp_strip_all_tags( $new_instance['title'] );
$instance['limit'] = $new_instance['limit'];
$instance['offset'] = $new_instance['offset'];
$instance['daily'] = $new_instance['daily'];
$instance['daily_range'] = $new_instance['daily_range'];
$instance['hour_range'] = $new_instance['hour_range'];
$instance['disp_list_count'] = isset( $new_instance['disp_list_count'] ) ? true : false;
$instance['show_excerpt'] = isset( $new_instance['show_excerpt'] ) ? true : false;
$instance['show_author'] = isset( $new_instance['show_author'] ) ? true : false;
$instance['show_date'] = isset( $new_instance['show_date'] ) ? true : false;
$instance['post_thumb_op'] = $new_instance['post_thumb_op'];
$instance['thumb_height'] = $new_instance['thumb_height'];
$instance['thumb_width'] = $new_instance['thumb_width'];
$instance['include_post_ids'] = implode( ',', array_filter( array_map( 'absint', explode( ',', $new_instance['include_post_ids'] ) ) ) );
// Process post types to be selected.
$wp_post_types = get_post_types(
array(
'public' => true,
)
);
$post_types = ( isset( $new_instance['post_types'] ) ) ? $new_instance['post_types'] : array();
$post_types = array_intersect( $wp_post_types, $post_types );
$instance['post_types'] = http_build_query( $post_types, '', '&' );
// Save include_categories.
$include_categories = array_unique( str_getcsv( $new_instance['include_categories'] ) );
foreach ( $include_categories as $cat_name ) {
$cat = get_term_by( 'name', $cat_name, 'category' );
if ( isset( $cat->term_taxonomy_id ) ) {
$include_cat_ids[] = $cat->term_taxonomy_id;
$include_cat_names[] = $cat->name;
}
}
$instance['include_cat_ids'] = isset( $include_cat_ids ) ? join( ',', $include_cat_ids ) : '';
$instance['include_categories'] = isset( $include_cat_names ) ? tptn_str_putcsv( $include_cat_names ) : '';
/**
* Filters Update widget options array.
*
* @since 2.0.0
*
* @param array $instance Widget options array
*/
return apply_filters( 'tptn_widget_options_update', $instance );
}
/**
* Front-end display of widget.
*
* @see WP_Widget::widget()
*
* @param array $args Widget arguments.
* @param array $instance Saved values from database.
*/
public function widget( $args, $instance ) {
global $post;
// Get the post meta.
if ( isset( $post ) ) {
$tptn_post_meta = get_post_meta( $post->ID, 'tptn_post_meta', true );
if ( isset( $tptn_post_meta['disable_here'] ) && ( $tptn_post_meta['disable_here'] ) ) {
return;
}
}
$title = apply_filters( 'widget_title', empty( $instance['title'] ) ? wp_strip_all_tags( tptn_get_option( 'title' ) ) : $instance['title'] );
$limit = isset( $instance['limit'] ) ? $instance['limit'] : tptn_get_option( 'limit' );
if ( empty( $limit ) ) {
$limit = tptn_get_option( 'limit' );
}
$offset = isset( $instance['offset'] ) ? $instance['offset'] : 0;
$daily_range = ( empty( $instance['daily_range'] ) ) ? tptn_get_option( 'daily_range' ) : $instance['daily_range'];
$hour_range = ( empty( $instance['hour_range'] ) ) ? tptn_get_option( 'hour_range' ) : $instance['hour_range'];
$daily = ( isset( $instance['daily'] ) && ( 'daily' === $instance['daily'] ) ) ? true : false;
$output = $args['before_widget'];
$output .= $args['before_title'] . $title . $args['after_title'];
$post_thumb_op = isset( $instance['post_thumb_op'] ) ? esc_attr( $instance['post_thumb_op'] ) : 'text_only';
$thumb_height = ( isset( $instance['thumb_height'] ) && '' !== $instance['thumb_height'] ) ? absint( $instance['thumb_height'] ) : tptn_get_option( 'thumb_height' );
$thumb_width = ( isset( $instance['thumb_width'] ) && '' !== $instance['thumb_width'] ) ? absint( $instance['thumb_width'] ) : tptn_get_option( 'thumb_width' );
$disp_list_count = isset( $instance['disp_list_count'] ) ? esc_attr( $instance['disp_list_count'] ) : '';
$show_excerpt = isset( $instance['show_excerpt'] ) ? esc_attr( $instance['show_excerpt'] ) : '';
$show_author = isset( $instance['show_author'] ) ? esc_attr( $instance['show_author'] ) : '';
$show_date = isset( $instance['show_date'] ) ? esc_attr( $instance['show_date'] ) : '';
$post_types = isset( $instance['post_types'] ) ? $instance['post_types'] : tptn_get_option( 'post_types' );
$include_cat_ids = isset( $instance['include_cat_ids'] ) ? esc_attr( $instance['include_cat_ids'] ) : '';
$include_post_ids = isset( $instance['include_post_ids'] ) ? esc_attr( $instance['include_post_ids'] ) : '';
$arguments = array(
'is_widget' => 1,
'instance_id' => $this->number,
'heading' => 0,
'limit' => $limit,
'offset' => $offset,
'daily' => $daily,
'daily_range' => $daily_range,
'hour_range' => $hour_range,
'show_excerpt' => $show_excerpt,
'show_author' => $show_author,
'show_date' => $show_date,
'post_thumb_op' => $post_thumb_op,
'thumb_height' => $thumb_height,
'thumb_width' => $thumb_width,
'disp_list_count' => $disp_list_count,
'post_types' => $post_types,
'include_cat_ids' => $include_cat_ids,
'include_post_ids' => $include_post_ids,
);
/**
* Filters arguments passed to tptn_pop_posts for the widget.
*
* @since 2.0.0
*
* @param array $arguments Widget options array
*/
$arguments = apply_filters( 'tptn_widget_options', $arguments );
$output .= tptn_pop_posts( $arguments );
$output .= $args['after_widget'];
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Add styles to the front end if the widget is active.
*
* @since 2.3.0
*/
public function front_end_styles() {
if ( ! 'left_thumbs' === tptn_get_option( 'tptn_styles' ) ) {
return;
}
// We need to process all instances because this function gets to run only once.
$widget_settings = get_option( $this->option_name );
foreach ( (array) $widget_settings as $instance => $options ) {
// Identify instance.
$widget_id = "{$this->id_base}-{$instance}";
// Check if it's our instance.
if ( ! is_active_widget( false, $widget_id, $this->id_base, true ) ) {
continue; // Not active.
}
$thumb_height = ( isset( $options['thumb_height'] ) && '' !== $options['thumb_height'] ) ? absint( $options['thumb_height'] ) : tptn_get_option( 'thumb_height' );
$thumb_width = ( isset( $options['thumb_width'] ) && '' !== $options['thumb_width'] ) ? absint( $options['thumb_width'] ) : tptn_get_option( 'thumb_width' );
// Enqueue the custom css for the thumb width and height for this specific widget.
$custom_css = "
.tptn_posts_widget{$instance} img.tptn_thumb {
width: {$thumb_width}px !important;
height: {$thumb_height}px !important;
}
";
wp_add_inline_style( 'tptn-style-left-thumbs', $custom_css );
}
}
}
/**
* Initialise the widget.
*/
function tptn_register_widget() {
register_widget( 'Top_Ten_Widget' );
}
add_action( 'widgets_init', 'tptn_register_widget', 1 );

View File

@@ -0,0 +1,47 @@
<?php
/**
* Exclusion modules
*
* @package Top_Ten
*/
/**
* Add additional post IDs to exclude. Filters `tptn_exclude_post_ids`.
*
* @since 2.2.0
*
* @param int[] $exclude_post_ids Original excluded post IDs.
* @return int[] Updated excluded post IDs array.
*/
function tptn_exclude_post_ids( $exclude_post_ids ) {
global $wpdb;
$exclude_post_ids = (array) $exclude_post_ids;
// Find all posts that have `exclude_this_post` set.
$tptn_post_metas = $wpdb->get_results( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE `meta_key` = 'tptn_post_meta'", ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
foreach ( $tptn_post_metas as $tptn_post_meta ) {
$meta_value = maybe_unserialize( $tptn_post_meta['meta_value'] );
if ( $meta_value['exclude_this_post'] ) {
$exclude_post_ids[] = $tptn_post_meta['post_id'];
}
}
// Exclude page_on_front and page_for_posts.
if ( 'page' === get_option( 'show_on_front' ) && tptn_get_option( 'exclude_front' ) ) {
$page_on_front = get_option( 'page_on_front' );
$page_for_posts = get_option( 'page_for_posts' );
if ( $page_on_front > 0 ) {
$exclude_post_ids[] = $page_on_front;
}
if ( $page_for_posts > 0 ) {
$exclude_post_ids[] = $page_for_posts;
}
}
return $exclude_post_ids;
}
add_filter( 'tptn_exclude_post_ids', 'tptn_exclude_post_ids' );

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,62 @@
<?php
/**
* Shortcode module
*
* @package Top_Ten
*/
/**
* Creates a shortcode [tptn_list limit="5" heading="1" daily="0"].
*
* @since 1.9.9
* @param array $atts Shortcode attributes.
* @param string $content Content.
* @return string Formatted list of posts generated by tptn_pop_posts
*/
function tptn_shortcode( $atts, $content = null ) {
global $tptn_settings;
$atts = shortcode_atts(
array_merge(
$tptn_settings,
array(
'heading' => 1,
'daily' => 0,
'is_shortcode' => 1,
'offset' => 0,
'include_cat_ids' => '',
)
),
$atts,
'top-10'
);
return tptn_pop_posts( $atts );
}
add_shortcode( 'tptn_list', 'tptn_shortcode' );
/**
* Creates a shortcode [tptn_views daily="0"].
*
* @since 1.9.9
* @param array $atts Shortcode attributes.
* @param string $content Content.
* @return string Views of the post
*/
function tptn_shortcode_views( $atts, $content = null ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$a = shortcode_atts(
array(
'daily' => '0',
'count' => 'total',
),
$atts
);
// If daily is explicitly set to 1, then pass daily, else pass count.
$count = $a['daily'] ? 'daily' : $a['count'];
return get_tptn_post_count_only( get_the_ID(), $count );
}
add_shortcode( 'tptn_views', 'tptn_shortcode_views' );

View File

@@ -0,0 +1,43 @@
<?php
/**
* Taxonomies control module
*
* @package Top_Ten
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Filter WHERE clause of tptn query to exclude posts belonging to certain categories.
*
* @since 2.2.0
*
* @param mixed $where WHERE clause.
* @return string Filtered WHERE clause
*/
function tptn_exclude_categories_where( $where ) {
global $wpdb, $tptn_settings;
if ( '' === tptn_get_option( 'exclude_categories' ) ) {
return $where;
} else {
$terms = tptn_get_option( 'exclude_categories' );
$sql = $where;
$sql .= " AND $wpdb->posts.ID NOT IN (
SELECT object_id
FROM $wpdb->term_relationships
WHERE term_taxonomy_id IN ($terms)
)";
return $sql;
}
}
add_filter( 'tptn_posts_where', 'tptn_exclude_categories_where' );

View File

@@ -0,0 +1,611 @@
<?php
/**
* Functions to fetch and display the posts
*
* @package Top_Ten
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Function to return formatted list of popular posts.
*
* @since 1.5
*
* @param mixed $args Arguments array.
* @return string HTML output of the popular posts.
*/
function tptn_pop_posts( $args ) {
global $tptn_settings;
// if set, save $exclude_categories.
if ( isset( $args['exclude_categories'] ) && '' != $args['exclude_categories'] ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$exclude_categories = explode( ',', $args['exclude_categories'] );
$args['strict_limit'] = false;
}
$defaults = array(
'daily' => false,
'is_widget' => false,
'instance_id' => 1,
'is_shortcode' => false,
'is_manual' => false,
'echo' => false,
'strict_limit' => false,
'heading' => 1,
'offset' => 0,
);
// Merge the $defaults array with the $tptn_settings array.
$defaults = array_merge( $defaults, tptn_settings_defaults(), $tptn_settings );
// Parse incomming $args into an array and merge it with $defaults.
$args = wp_parse_args( $args, $defaults );
$output = '';
/**
* Fires before the output processing begins.
*
* @since 2.2.0
*
* @param string $output Formatted list of top posts
* @param array $args Array of arguments
*/
do_action( 'pre_tptn_pop_posts', $output, $args );
// Check if the cache is enabled and if the output exists. If so, return the output.
if ( $args['cache'] ) {
$cache_name = tptn_cache_get_key( $args );
$output = get_transient( $cache_name );
if ( false !== $output ) {
/**
* Filter the output
*
* @since 1.9.8.5
*
* @param string $output Formatted list of top posts
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_pop_posts', $output, $args );
}
}
// Get thumbnail size.
list( $args['thumb_width'], $args['thumb_height'] ) = tptn_get_thumb_size( $args );
// Retrieve the popular posts.
$results = get_tptn_posts( $args );
$counter = 0;
$daily_class = $args['daily'] ? 'tptn_posts_daily ' : 'tptn_posts ';
$widget_class = $args['is_widget'] ? ' tptn_posts_widget tptn_posts_widget' . $args['instance_id'] : '';
$shortcode_class = $args['is_shortcode'] ? ' tptn_posts_shortcode' : '';
$post_classes = $daily_class . $widget_class . $shortcode_class;
/**
* Filter the classes added to the div wrapper of the Top 10.
*
* @since 2.1.0
*
* @param string $post_classes Post classes string.
*/
$post_classes = apply_filters( 'tptn_post_class', $post_classes );
$output .= '<div class="' . $post_classes . '">';
if ( $results ) {
$output .= tptn_heading_title( $args );
$output .= tptn_before_list( $args );
// We need this for WPML support.
$processed_results = array();
foreach ( $results as $result ) {
/* Support WPML */
$resultid = tptn_object_id_cur_lang( $result->ID );
// If this is NULL or already processed ID or matches current post then skip processing this loop.
if ( ! $resultid || in_array( $resultid, $processed_results ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
continue;
}
// Push the current ID into the array to ensure we're not repeating it.
array_push( $processed_results, $resultid );
// Store the count. We'll need this later.
$count = $args['daily'] ? 'daily' : 'total';
$visits = empty( $result->visits ) ? get_tptn_post_count_only( $resultid, $count ) : $result->visits;
/**
* Filter the post ID for each result. Allows a custom function to hook in and change the ID if needed.
*
* @since 1.9.8.5
*
* @param int $resultid ID of the post
*/
$resultid = apply_filters( 'tptn_post_id', $resultid );
$result = get_post( $resultid ); // Let's get the Post using the ID.
// Process the category exclusion if passed in the shortcode.
if ( isset( $exclude_categories ) ) {
$categorys = get_the_category( $result->ID ); // Fetch categories of the plugin.
$p_in_c = false; // Variable to check if post exists in a particular category.
foreach ( $categorys as $cat ) { // Loop to check if post exists in excluded category.
$p_in_c = ( in_array( $cat->cat_ID, $exclude_categories ) ) ? true : false; // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
if ( $p_in_c ) {
break; // Skip loop execution and go to the next step.
}
}
if ( $p_in_c ) {
continue; // Skip loop execution and go to the next step.
}
}
$output .= tptn_before_list_item( $args, $result );
$output .= tptn_list_link( $args, $result );
if ( $args['show_author'] ) {
$output .= tptn_author( $args, $result );
}
if ( $args['show_date'] ) {
$output .= '<span class="tptn_date"> ' . tptn_date( $args, $result ) . '</span> ';
}
if ( $args['show_excerpt'] ) {
$output .= '<span class="tptn_excerpt"> ' . tptn_excerpt( $result->ID, $args['excerpt_length'] ) . '</span>';
}
if ( $args['disp_list_count'] ) {
$output .= ' <span class="tptn_list_count">' . tptn_list_count( $args, $result, $visits ) . '</span>';
}
$tptn_list = '';
/**
* Filter to add content to the end of each item in the list.
*
* @since 2.2.0
*
* @param string $tptn_list Empty string at the end of each list item.
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
$output .= apply_filters( 'tptn_list', $tptn_list, $result, $args );
// Opening span created in tptn_list_link().
if ( 'inline' === $args['post_thumb_op'] || 'text_only' === $args['post_thumb_op'] ) {
$output .= '</span>';
}
$output .= tptn_after_list_item( $args, $result );
$counter++;
if ( $counter === (int) $args['limit'] ) {
break; // End loop when related posts limit is reached.
}
}
if ( $args['show_credit'] ) {
$output .= tptn_before_list_item( $args, $result );
$output .= sprintf(
/* translators: 1. Top 10 plugin page link, 2. Link attributes. */
__( 'Popular posts by <a href="%1$s" rel="nofollow" %2$s>Top 10 plugin</a>', 'top-10' ),
esc_url( 'https://webberzone.com/plugins/top-10/' ),
tptn_link_attributes( $args, $result )
);
$output .= tptn_after_list_item( $args, $result );
}
$output .= tptn_after_list( $args );
$clearfix = '<div class="tptn_clear"></div>';
/**
* Filter the clearfix div tag. This is included after the closing tag to clear any miscellaneous floating elements;
*
* @since 2.2.0
*
* @param string $clearfix Contains: <div style="clear:both"></div>
*/
$output .= apply_filters( 'tptn_clearfix', $clearfix );
} else {
$output .= ( $args['blank_output'] ) ? '' : $args['blank_output_text'];
}
$output .= '</div>';
// Check if the cache is enabled and if the output exists. If so, return the output.
if ( $args['cache'] ) {
/**
* Filter the cache time which allows a function to override this
*
* @since 2.2.0
*
* @param int $args['cache_time'] Cache time in seconds
* @param array $args Array of all the arguments
*/
$cache_time = apply_filters( 'tptn_cache_time', $args['cache_time'], $args );
$output .= "<br /><!-- Cached output. Cached time is {$cache_time} seconds -->";
set_transient( $cache_name, $output, $cache_time );
}
/**
* Filter already documented in top-10.php
*/
return apply_filters( 'tptn_pop_posts', $output, $args );
}
/**
* Function to retrieve the popular posts.
*
* @since 2.1.0
*
* @param mixed $args Arguments list.
*/
function get_tptn_pop_posts( $args = array() ) {
global $wpdb, $tptn_settings;
// Initialise some variables.
$fields = array();
$where = '';
$join = '';
$groupby = '';
$orderby = '';
$limits = '';
$defaults = array(
'daily' => false,
'strict_limit' => true,
'posts_only' => false,
'offset' => 0,
);
// Merge the $defaults array with the $tptn_settings array.
$defaults = array_merge( $defaults, tptn_settings_defaults(), $tptn_settings );
// Parse incomming $args into an array and merge it with $defaults.
$args = wp_parse_args( $args, $defaults );
if ( $args['daily'] ) {
$table_name = $wpdb->base_prefix . 'top_ten_daily';
} else {
$table_name = $wpdb->base_prefix . 'top_ten';
}
$limit = ( $args['strict_limit'] ) ? $args['limit'] : ( $args['limit'] * 5 );
$offset = isset( $args['offset'] ) ? $args['offset'] : 0;
// If post_types is empty or contains a query string then use parse_str else consider it comma-separated.
if ( ! empty( $args['post_types'] ) && is_array( $args['post_types'] ) ) {
$post_types = $args['post_types'];
} elseif ( ! empty( $args['post_types'] ) && false === strpos( $args['post_types'], '=' ) ) {
$post_types = explode( ',', $args['post_types'] );
} else {
parse_str( $args['post_types'], $post_types ); // Save post types in $post_types variable.
}
// If post_types is empty or if we want all the post types.
if ( empty( $post_types ) || 'all' === $args['post_types'] ) {
$post_types = get_post_types(
array(
'public' => true,
)
);
}
$blog_id = get_current_blog_id();
$from_date = tptn_get_from_date( null, $args['daily_range'], $args['hour_range'] );
/**
*
* We're going to create a mySQL query that is fully extendable which would look something like this:
* "SELECT $fields FROM $wpdb->posts $join WHERE 1=1 $where $groupby $orderby $limits"
*/
// Fields to return.
$fields[] = "{$table_name}.postnumber";
$fields[] = ( $args['daily'] ) ? "SUM({$table_name}.cntaccess) as visits" : "{$table_name}.cntaccess as visits";
$fields[] = "{$wpdb->posts}.ID";
$fields = implode( ', ', $fields );
// Create the JOIN clause.
$join = " INNER JOIN {$wpdb->posts} ON {$table_name}.postnumber={$wpdb->posts}.ID ";
// Create the base WHERE clause.
$where .= $wpdb->prepare( " AND {$table_name}.blog_id = %d ", $blog_id ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$where .= " AND ({$wpdb->posts}.post_status = 'publish' OR {$wpdb->posts}.post_status = 'inherit') "; // Show published posts and attachments.
if ( $args['daily'] ) {
$where .= $wpdb->prepare( " AND {$table_name}.dp_date >= %s ", $from_date ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
// Convert exclude post IDs string to array so it can be filtered.
$exclude_post_ids = explode( ',', $args['exclude_post_ids'] );
/** This filter is documented in class-top-ten-query.php */
$exclude_post_ids = apply_filters( 'tptn_exclude_post_ids', $exclude_post_ids );
// Convert it back to string.
$exclude_post_ids = implode( ',', array_filter( $exclude_post_ids ) );
if ( '' != $exclude_post_ids ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$where .= " AND $wpdb->posts.ID NOT IN ({$exclude_post_ids}) ";
}
$where .= " AND $wpdb->posts.post_type IN ('" . join( "', '", $post_types ) . "') "; // Array of post types.
// How old should the posts be?
if ( $args['how_old'] ) {
$how_old_date = tptn_get_from_date( null, $args['how_old'] + 1, 0 );
$where .= $wpdb->prepare( " AND $wpdb->posts.post_date > %s ", $how_old_date );
}
if ( isset( $args['include_cat_ids'] ) && ! empty( $args['include_cat_ids'] ) ) {
$include_cat_ids = $args['include_cat_ids'];
$where .= " AND $wpdb->posts.ID IN ( SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id IN ($include_cat_ids) )";
}
// Create the base GROUP BY clause.
if ( $args['daily'] ) {
$groupby = ' postnumber ';
}
// Create the base ORDER BY clause.
$orderby = ' visits DESC ';
// Create the base LIMITS clause.
$limits .= $wpdb->prepare( ' LIMIT %d, %d ', $offset, $limit );
/**
* Filter the SELECT clause of the query.
*
* @param string $fields The SELECT clause of the query.
*/
$fields = apply_filters( 'tptn_posts_fields', $fields );
/**
* Filter the JOIN clause of the query.
*
* @param string $join The JOIN clause of the query.
*/
$join = apply_filters( 'tptn_posts_join', $join );
/**
* Filter the WHERE clause of the query.
*
* @param string $where The WHERE clause of the query.
*/
$where = apply_filters( 'tptn_posts_where', $where );
/**
* Filter the GROUP BY clause of the query.
*
* @param string $groupby The GROUP BY clause of the query.
*/
$groupby = apply_filters( 'tptn_posts_groupby', $groupby );
/**
* Filter the ORDER BY clause of the query.
*
* @param string $orderby The ORDER BY clause of the query.
*/
$orderby = apply_filters( 'tptn_posts_orderby', $orderby );
/**
* Filter the LIMIT clause of the query.
*
* @param string $limits The LIMIT clause of the query.
*/
$limits = apply_filters( 'tptn_posts_limits', $limits );
if ( ! empty( $groupby ) ) {
$groupby = " GROUP BY {$groupby} ";
}
if ( ! empty( $orderby ) ) {
$orderby = " ORDER BY {$orderby} ";
}
$sql = "SELECT DISTINCT $fields FROM {$table_name} $join WHERE 1=1 $where $groupby $orderby $limits";
if ( $args['posts_only'] ) { // Return the array of posts only if the variable is set.
$results = $wpdb->get_results( $sql, ARRAY_A ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
/**
* Filter the array of top post IDs.
*
* @since 1.9.8.5
*
* @param array $tptn_pop_posts_array Posts array.
* @param mixed $args Arguments list
*/
return apply_filters( 'tptn_pop_posts_array', $results, $args );
}
$results = $wpdb->get_results( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
/**
* Filter object containing post IDs of popular posts
*
* @since 2.1.0
*
* @param object $results Top 10 popular posts object
* @param mixed $args Arguments list
*/
return apply_filters( 'get_tptn_pop_posts', $results, $args );
}
/**
* Function to echo popular posts.
*
* @since 1.0
*
* @param mixed $args Arguments list.
*/
function tptn_show_pop_posts( $args = null ) {
if ( is_array( $args ) ) {
$args['manual'] = 1;
} else {
$args .= '&is_manual=1';
}
echo tptn_pop_posts( $args ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Function to show daily popular posts.
*
* @since 1.2
*
* @param mixed $args Arguments list.
*/
function tptn_show_daily_pop_posts( $args = null ) {
if ( is_array( $args ) || ! isset( $args ) ) {
$args['daily'] = 1;
} else {
$args .= '&daily=1';
}
tptn_show_pop_posts( $args );
}
/**
* Add custom feeds for the overall and daily popular posts.
*
* @since 2.8.0
*
* @return void
*/
function tptn_pop_posts_feed() {
$popular_posts_overall = tptn_get_option( 'feed_permalink_overall' );
$popular_posts_daily = tptn_get_option( 'feed_permalink_daily' );
if ( ! empty( $popular_posts_overall ) ) {
add_feed( $popular_posts_overall, 'tptn_pop_posts_feed_overall' );
}
if ( ! empty( $popular_posts_daily ) ) {
add_feed( $popular_posts_daily, 'tptn_pop_posts_feed_daily' );
}
}
add_action( 'init', 'tptn_pop_posts_feed' );
/**
* Callback for overall popular posts.
*
* @since 2.8.0
*
* @return void
*/
function tptn_pop_posts_feed_overall() {
tptn_pop_posts_feed_callback( false );
}
/**
* Callback for daily popular posts.
*
* @since 2.8.0
*
* @return void
*/
function tptn_pop_posts_feed_daily() {
tptn_pop_posts_feed_callback( true );
}
/**
* Callback function for add_feed to locate the correct template.
*
* @since 2.8.0
*
* @param bool $daily Daily posts flag.
*
* @return void
*/
function tptn_pop_posts_feed_callback( $daily = false ) {
add_filter( 'pre_option_rss_use_excerpt', '__return_zero' );
set_query_var( 'daily', $daily );
$template = locate_template( 'feed-rss2-popular-posts.php' );
if ( ! $template ) {
$template = TOP_TEN_PLUGIN_DIR . 'includes/public/feed-rss2-popular-posts.php';
}
if ( $template ) {
load_template( $template );
}
}
/**
* Get the key based on a list of parameters.
*
* @since 2.9.3
*
* @param array $attr Array of attributes.
* @return string Cache key
*/
function tptn_cache_get_key( $attr ) {
$key = 'tptn_cache_' . md5( wp_json_encode( $attr ) );
return $key;
}
/**
* Retrieves an array of the related posts.
*
* The defaults are as follows:
*
* @since 3.0.0
*
* @see Top_Ten_Query::prepare_query_args()
*
* @param array $args Optional. Arguments to retrieve posts. See WP_Query::parse_query() for all available arguments.
* @return WP_Post[]|int[] Array of post objects or post IDs.
*/
function get_tptn_posts( $args = array() ) {
$get_tptn_posts = new Top_Ten_Query( $args );
/**
* Filter array of post IDs or objects.
*
* @since 3.0.0
*
* @param WP_Post[]|int[] $posts Array of post objects or post IDs.
* @param array $args Arguments to retrieve posts.
*/
return apply_filters( 'get_tptn_posts', $get_tptn_posts->posts, $args );
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* RSS2 Feed Template for displaying RSS2 Posts feed for the Top 10 Popular posts.
*
* @package TOP_TEN
*/
$settings = array(
'daily' => $daily,
'daily_range' => tptn_get_option( 'feed_daily_range' ),
'limit' => tptn_get_option( 'feed_limit' ),
);
$topposts = get_tptn_posts( $settings );
$topposts = wp_list_pluck( (array) $topposts, 'postnumber' );
$args = array(
'post__in' => $topposts,
'orderby' => 'post__in',
'posts_per_page' => count( $topposts ),
);
query_posts( $args ); // phpcs:ignore WordPress.WP.DiscouragedFunctions.query_posts_query_posts
header( 'Content-Type: ' . feed_content_type( 'rss2' ) . '; charset=' . get_option( 'blog_charset' ), true );
$more = 1; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
echo '<?xml version="1.0" encoding="' . esc_attr( get_option( 'blog_charset' ) ) . '"?' . '>';
/**
* Fires between the xml and rss tags in a feed.
*
* @since 4.0.0
*
* @param string $context Type of feed. Possible values include 'rss2', 'rss2-comments',
* 'rdf', 'atom', and 'atom-comments'.
*/
do_action( 'rss_tag_pre', 'rss2' );
?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
<?php
/**
* Fires at the end of the RSS root to add namespaces.
*
* @since 2.0.0
*/
do_action( 'rss2_ns' );
?>
>
<channel>
<title><?php wp_title_rss(); ?></title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<link><?php bloginfo_rss( 'url' ); ?></link>
<description><?php bloginfo_rss( 'description' ); ?></description>
<lastBuildDate><?php echo get_feed_build_date( 'r' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></lastBuildDate>
<language><?php bloginfo_rss( 'language' ); ?></language>
<sy:updatePeriod>
<?php
$duration = 'hourly';
/**
* Filters how often to update the RSS feed.
*
* @since 2.1.0
*
* @param string $duration The update period. Accepts 'hourly', 'daily', 'weekly', 'monthly',
* 'yearly'. Default 'hourly'.
*/
echo apply_filters( 'rss_update_period', $duration ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</sy:updatePeriod>
<sy:updateFrequency>
<?php
$frequency = '1';
/**
* Filters the RSS update frequency.
*
* @since 2.1.0
*
* @param string $frequency An integer passed as a string representing the frequency
* of RSS updates within the update period. Default '1'.
*/
echo apply_filters( 'rss_update_frequency', $frequency ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
</sy:updateFrequency>
<?php
/**
* Fires at the end of the RSS2 Feed Header.
*
* @since 2.0.0
*/
do_action( 'rss2_head' );
while ( have_posts() ) :
the_post();
?>
<item>
<title><?php the_title_rss(); ?></title>
<link><?php the_permalink_rss(); ?></link>
<?php if ( get_comments_number() || comments_open() ) : ?>
<comments><?php comments_link_feed(); ?></comments>
<?php endif; ?>
<pubDate><?php echo mysql2date( 'D, d M Y H:i:s +0000', get_post_time( 'Y-m-d H:i:s', true ), false ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></pubDate>
<dc:creator><![CDATA[<?php the_author(); ?>]]></dc:creator>
<?php the_category_rss( 'rss2' ); ?>
<guid isPermaLink="false"><?php the_guid(); ?></guid>
<?php if ( get_option( 'rss_use_excerpt' ) ) : ?>
<description><![CDATA[<?php the_excerpt_rss(); ?>]]></description>
<?php else : ?>
<description><![CDATA[<?php the_excerpt_rss(); ?>]]></description>
<?php $content = get_the_content_feed( 'rss2' ); ?>
<?php if ( strlen( $content ) > 0 ) : ?>
<content:encoded><![CDATA[<?php echo $content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>]]></content:encoded>
<?php else : ?>
<content:encoded><![CDATA[<?php the_excerpt_rss(); ?>]]></content:encoded>
<?php endif; ?>
<?php endif; ?>
<?php if ( get_comments_number() || comments_open() ) : ?>
<wfw:commentRss><?php echo esc_url( get_post_comments_feed_link( null, 'rss2' ) ); ?></wfw:commentRss>
<slash:comments><?php echo get_comments_number(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></slash:comments>
<?php endif; ?>
<?php rss_enclosure(); ?>
<?php
/**
* Fires at the end of each RSS2 feed item.
*
* @since 2.0.0
*/
do_action( 'rss2_item' );
?>
</item>
<?php endwhile; ?>
</channel>
</rss>

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1,543 @@
<?php
/**
* Media handler
*
* @package Top_Ten
*/
/**
* Add custom image size of thumbnail. Filters `init`.
*
* @since 2.0.0
*/
function tptn_add_image_sizes() {
$thumb_size = tptn_get_option( 'thumb_size' );
if ( ! in_array( $thumb_size, get_intermediate_image_sizes() ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
$thumb_size = 'tptn_thumbnail';
}
// Add image sizes if 'tptn_thumbnail' is selected or the selected thumbnail size is no longer valid.
if ( 'tptn_thumbnail' === $thumb_size && tptn_get_option( 'thumb_create_sizes' ) ) {
$width = tptn_get_option( 'thumb_width', 150 );
$height = tptn_get_option( 'thumb_height', 150 );
$crop = tptn_get_option( 'thumb_crop', true );
add_image_size( 'tptn_thumbnail', $width, $height, $crop );
}
}
add_action( 'init', 'tptn_add_image_sizes' );
/**
* Function to get the post thumbnail.
*
* @since 1.8
* @param array $args Query string of options related to thumbnails.
* @return string Image tag
*/
function tptn_get_the_post_thumbnail( $args = array() ) {
$defaults = array(
'postid' => '',
'thumb_height' => '150', // Max height of thumbnails.
'thumb_width' => '150', // Max width of thumbnails.
'thumb_meta' => 'post-image', // Meta field that is used to store the location of default thumbnail image.
'thumb_html' => 'html', // HTML / CSS for width and height attributes.
'thumb_default' => '', // Default thumbnail image.
'thumb_default_show' => true, // Show default thumb if none found (if false, don't show thumb at all).
'scan_images' => false, // Scan post for images.
'class' => 'tptn_thumb', // Class of the thumbnail.
);
// Parse incomming $args into an array and merge it with $defaults.
$args = wp_parse_args( $args, $defaults );
// Issue notice for deprecated arguments.
if ( isset( $args['thumb_timthumb'] ) ) {
_deprecated_argument( __FUNCTION__, '2.1', esc_html__( 'thumb_timthumb argument has been deprecated', 'top-10' ) );
}
if ( isset( $args['thumb_timthumb_q'] ) ) {
_deprecated_argument( __FUNCTION__, '2.1', esc_html__( 'thumb_timthumb_q argument has been deprecated', 'top-10' ) );
}
if ( isset( $args['filter'] ) ) {
_deprecated_argument( __FUNCTION__, '2.1', esc_html__( 'filter argument has been deprecated', 'top-10' ) );
}
if ( is_int( $args['postid'] ) ) {
$result = get_post( $args['postid'] );
} else {
$result = $args['postid'];
}
$post_title = esc_attr( $result->post_title );
/**
* Filters the title and alt message for thumbnails.
*
* @since 2.3.0
*
* @param string $post_title Post tile used as thumbnail alt and title
* @param object $result Post Object
*/
$post_title = apply_filters( 'tptn_thumb_title', $post_title, $result );
$output = '';
$postimage = '';
$pick = '';
// Let's start fetching the thumbnail. First place to look is in the post meta defined in the Settings page.
if ( ! $postimage ) {
$postimage = get_post_meta( $result->ID, $args['thumb_meta'], true );
$pick = 'meta';
if ( $postimage ) {
$postimage_id = tptn_get_attachment_id_from_url( $postimage );
if ( false != wp_get_attachment_image_src( $postimage_id, array( $args['thumb_width'], $args['thumb_height'] ) ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$postthumb = wp_get_attachment_image_src( $postimage_id, array( $args['thumb_width'], $args['thumb_height'] ) );
$postimage = $postthumb[0];
}
$pick .= 'correct';
}
}
// If there is no thumbnail found, check the post thumbnail.
if ( ! $postimage ) {
if ( false != get_post_thumbnail_id( $result->ID ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$postthumb = wp_get_attachment_image_src( get_post_thumbnail_id( $result->ID ), array( $args['thumb_width'], $args['thumb_height'] ) );
if ( false !== $postthumb ) {
$postimage = $postthumb[0];
$pick = 'featured';
}
}
}
// If there is no thumbnail found, fetch the first image in the post, if enabled.
if ( ! $postimage && $args['scan_images'] ) {
preg_match_all( '/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $result->post_content, $matches );
if ( isset( $matches[1][0] ) && $matches[1][0] ) { // any image there?
$postimage = $matches[1][0]; // we need the first one only!
}
$pick = 'first';
if ( $postimage ) {
$postimage_id = tptn_get_attachment_id_from_url( $postimage );
if ( false != wp_get_attachment_image_src( $postimage_id, array( $args['thumb_width'], $args['thumb_height'] ) ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$postthumb = wp_get_attachment_image_src( $postimage_id, array( $args['thumb_width'], $args['thumb_height'] ) );
$postimage = $postthumb[0];
$pick .= 'correct';
}
}
}
// If there is no thumbnail found, fetch the first child image.
if ( ! $postimage ) {
$postimage = tptn_get_first_image( $result->ID, $args['thumb_width'], $args['thumb_height'] ); // Get the first image.
$pick = 'firstchild';
}
// If no other thumbnail set, try to get the custom video thumbnail set by the Video Thumbnails plugin.
if ( ! $postimage ) {
$postimage = get_post_meta( $result->ID, '_video_thumbnail', true );
$pick = 'video_thumb';
}
// If no thumb found and settings permit, use default thumb.
if ( ! $postimage && $args['thumb_default_show'] ) {
$postimage = $args['thumb_default'];
$pick = 'default_thumb';
}
// Hopefully, we've found a thumbnail by now. If so, run it through the custom filter, check for SSL and create the image tag.
if ( $postimage ) {
/**
* Filters the thumbnail image URL.
*
* Use this filter to modify the thumbnail URL that is automatically created
* Before v2.1 this was used for cropping the post image using timthumb
*
* @since 2.1.0
*
* @param string $postimage URL of the thumbnail image
* @param int $thumb_width Thumbnail width
* @param int $thumb_height Thumbnail height
* @param object $result Post Object
*/
$postimage = apply_filters( 'tptn_thumb_url', $postimage, $args['thumb_width'], $args['thumb_height'], $result );
/* Backward compatibility */
$thumb_timthumb = false;
$thumb_timthumb_q = 75;
/**
* Filters the thumbnail image URL.
*
* @since 1.8.10
* @deprecated 2.1.0 Use tptn_thumb_url instead.
*
* @param string $postimage URL of the thumbnail image
* @param int $thumb_width Thumbnail width
* @param int $thumb_height Thumbnail height
* @param boolean $thumb_timthumb Enable timthumb?
* @param int $thumb_timthumb_q Quality of timthumb thumbnail.
* @param object $result Post Object
*/
$postimage = apply_filters( 'tptn_postimage', $postimage, $args['thumb_width'], $args['thumb_height'], $thumb_timthumb, $thumb_timthumb_q, $result );
if ( is_ssl() ) {
$postimage = preg_replace( '~http://~', 'https://', $postimage );
}
$class = $args['class'] . ' tptn_' . $pick;
/**
* Filters the thumbnail classes and allows a filter function to add any more classes if needed.
*
* @since 2.2.0
*
* @param string $class Thumbnail Class
*/
$attr['class'] = apply_filters( 'tptn_thumb_class', $class );
/**
* Filters the thumbnail alt.
*
* @since 2.6.0
*
* @param string $post_title Thumbnail alt attribute
*/
$attr['alt'] = apply_filters( 'tptn_thumb_alt', $post_title );
/**
* Filters the thumbnail title.
*
* @since 2.6.0
*
* @param string $post_title Thumbnail title attribute
*/
$attr['title'] = apply_filters( 'tptn_thumb_title', $post_title );
$attr['thumb_html'] = $args['thumb_html'];
$attr['thumb_width'] = $args['thumb_width'];
$attr['thumb_height'] = $args['thumb_height'];
$output .= tptn_get_image_html( $postimage, $attr );
}
/**
* Filters post thumbnail created for Top 10.
*
* @since 1.9.10.1
*
* @param array $output Formatted output
* @param array $args Argument list
* @param string $postimage Thumbnail URL
*/
return apply_filters( 'tptn_get_the_post_thumbnail', $output, $args, $postimage );
}
/**
* Get an HTML img element
*
* @since 2.6.0
*
* @param string $attachment_url Image URL.
* @param array $attr Attributes for the image markup.
* @return string HTML img element or empty string on failure.
*/
function tptn_get_image_html( $attachment_url, $attr = array() ) {
// If there is no url, return.
if ( '' == $attachment_url ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
return;
}
$default_attr = array(
'src' => $attachment_url,
'thumb_html' => tptn_get_option( 'thumb_html', 'html' ),
'thumb_width' => tptn_get_option( 'thumb_width', 150 ),
'thumb_height' => tptn_get_option( 'thumb_height', 150 ),
);
$attr = wp_parse_args( $attr, $default_attr );
$hwstring = tptn_get_image_hwstring( $attr );
// Generate 'srcset' and 'sizes' if not already present.
if ( empty( $attr['srcset'] ) ) {
$attachment_id = tptn_get_attachment_id_from_url( $attachment_url );
$image_meta = wp_get_attachment_metadata( $attachment_id );
if ( is_array( $image_meta ) ) {
$size_array = array( absint( $attr['thumb_width'] ), absint( $attr['thumb_height'] ) );
$srcset = wp_calculate_image_srcset( $size_array, $attachment_url, $image_meta, $attachment_id );
$sizes = wp_calculate_image_sizes( $size_array, $attachment_url, $image_meta, $attachment_id );
if ( $srcset && ( $sizes || ! empty( $attr['sizes'] ) ) ) {
$attr['srcset'] = $srcset;
if ( empty( $attr['sizes'] ) ) {
$attr['sizes'] = $sizes;
}
}
}
}
// Unset attributes we don't want to display.
unset( $attr['thumb_html'] );
unset( $attr['thumb_width'] );
unset( $attr['thumb_height'] );
/**
* Filters the list of attachment image attributes.
*
* @since 2.6.0
*
* @param array $attr Attributes for the image markup.
* @param string $attachment_url Image URL.
*/
$attr = apply_filters( 'tptn_get_image_attributes', $attr, $attachment_url );
$attr = array_map( 'esc_attr', $attr );
$html = '<img ' . $hwstring;
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
return apply_filters( 'tptn_get_image_html', $html );
}
/**
* Retrieve width and height attributes using given width and height values.
*
* @since 2.6.0
*
* @param array $args Argument array.
*
* @return string Height-width string.
*/
function tptn_get_image_hwstring( $args = array() ) {
$default_args = array(
'thumb_html' => tptn_get_option( 'thumb_html', 'html' ),
'thumb_width' => tptn_get_option( 'thumb_width', 150 ),
'thumb_height' => tptn_get_option( 'thumb_height', 150 ),
);
$args = wp_parse_args( $args, $default_args );
if ( 'css' === $args['thumb_html'] ) {
$thumb_html = ' style="max-width:' . $args['thumb_width'] . 'px;max-height:' . $args['thumb_height'] . 'px;" ';
} elseif ( 'html' === $args['thumb_html'] ) {
$thumb_html = ' width="' . $args['thumb_width'] . '" height="' . $args['thumb_height'] . '" ';
} else {
$thumb_html = '';
}
/**
* Filters the thumbnail HTML and allows a filter function to add any more HTML if needed.
*
* @since 2.2.0
*
* @param string $thumb_html Thumbnail HTML.
* @param array $args Argument array.
*/
return apply_filters( 'tptn_thumb_html', $thumb_html, $args );
}
/**
* Get the first child image in the post.
*
* @since 1.9.8
* @param mixed $postid Post ID.
* @param int $thumb_width Thumb width.
* @param int $thumb_height Thumb height.
* @return string Location of thumbnail
*/
function tptn_get_first_image( $postid, $thumb_width, $thumb_height ) {
$args = array(
'numberposts' => 1,
'order' => 'ASC',
'post_mime_type' => 'image',
'post_parent' => $postid,
'post_status' => null,
'post_type' => 'attachment',
);
$attachments = get_children( $args );
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
$image_attributes = wp_get_attachment_image_src( $attachment->ID, array( $thumb_width, $thumb_height ) ) ? wp_get_attachment_image_src( $attachment->ID, array( $thumb_width, $thumb_height ) ) : wp_get_attachment_image_src( $attachment->ID, 'full' );
/**
* Filters first child attachment from the post.
*
* @since 1.9.10.1
*
* @param array $image_attributes[0] URL of the image
* @param int $postid Post ID
* @param int $thumb_width Thumb width
* @param int $thumb_height Thumb height
*/
return apply_filters( 'tptn_get_first_image', $image_attributes[0], $postid, $thumb_width, $thumb_height );
}
} else {
return false;
}
}
/**
* Function to get the attachment ID from the attachment URL.
*
* @since 2.1
*
* @param string $attachment_url Attachment URL.
* @return int Attachment ID
*/
function tptn_get_attachment_id_from_url( $attachment_url = '' ) {
global $wpdb;
$attachment_id = false;
// If there is no url, return.
if ( '' == $attachment_url ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
return;
}
// Get the upload directory paths.
$upload_dir_paths = wp_upload_dir();
// Make sure the upload path base directory exists in the attachment URL, to verify that we're working with a media library image.
if ( false !== strpos( $attachment_url, $upload_dir_paths['baseurl'] ) ) {
// If this is the URL of an auto-generated thumbnail, get the URL of the original image.
$attachment_url = preg_replace( '/-\d+x\d+(?=\.(jpg|jpeg|png|gif)$)/i', '', $attachment_url );
// Remove the upload path base directory from the attachment URL.
$attachment_url = str_replace( $upload_dir_paths['baseurl'] . '/', '', $attachment_url );
// Finally, run a custom database query to get the attachment ID from the modified attachment URL.
$attachment_id = $wpdb->get_var( $wpdb->prepare( "SELECT wposts.ID FROM $wpdb->posts wposts, $wpdb->postmeta wpostmeta WHERE wposts.ID = wpostmeta.post_id AND wpostmeta.meta_key = '_wp_attached_file' AND wpostmeta.meta_value = %s AND wposts.post_type = 'attachment'", $attachment_url ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
/**
* Filter the attachment ID from the attachment URL.
*
* @since 2.1
*
* @param int Attachment ID
* @param string $attachment_url Attachment URL
*/
return apply_filters( 'tptn_get_attachment_id_from_url', $attachment_id, $attachment_url );
}
/**
* Function to get the correct height and width of the thumbnail.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @return array Width and height
*/
function tptn_get_thumb_size( $args ) {
// Get thumbnail size.
$tptn_thumb_size = tptn_get_all_image_sizes( $args['thumb_size'] );
if ( isset( $tptn_thumb_size['width'] ) ) {
$thumb_width = $tptn_thumb_size['width'];
$thumb_height = $tptn_thumb_size['height'];
}
if ( empty( $thumb_width ) || ( $args['is_widget'] && $thumb_width != $args['thumb_width'] ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$thumb_width = $args['thumb_width'];
$args['thumb_html'] = 'css';
}
if ( empty( $thumb_height ) || ( $args['is_widget'] && $thumb_height != $args['thumb_height'] ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
$thumb_height = $args['thumb_height'];
$args['thumb_html'] = 'css';
}
$thumb_size = array( $thumb_width, $thumb_height );
/**
* Filter array of thumbnail size.
*
* @since 2.2.0
*
* @param array $thumb_size Array with width and height of thumbnail
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_get_thumb_size', $thumb_size, $args );
}
/**
* Get all image sizes.
*
* @since 2.0.0
* @param string $size Get specific image size.
* @return array Image size names along with width, height and crop setting
*/
function tptn_get_all_image_sizes( $size = '' ) {
global $_wp_additional_image_sizes;
/* Get the intermediate image sizes and add the full size to the array. */
$intermediate_image_sizes = get_intermediate_image_sizes();
foreach ( $intermediate_image_sizes as $_size ) {
if ( in_array( $_size, array( 'thumbnail', 'medium', 'large' ) ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
$sizes[ $_size ]['name'] = $_size;
$sizes[ $_size ]['width'] = get_option( $_size . '_size_w' );
$sizes[ $_size ]['height'] = get_option( $_size . '_size_h' );
$sizes[ $_size ]['crop'] = (bool) get_option( $_size . '_crop' );
if ( ( 0 == $sizes[ $_size ]['width'] ) && ( 0 == $sizes[ $_size ]['height'] ) ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
unset( $sizes[ $_size ] );
}
} elseif ( isset( $_wp_additional_image_sizes[ $_size ] ) ) {
$sizes[ $_size ] = array(
'name' => $_size,
'width' => $_wp_additional_image_sizes[ $_size ]['width'],
'height' => $_wp_additional_image_sizes[ $_size ]['height'],
'crop' => (bool) $_wp_additional_image_sizes[ $_size ]['crop'],
);
}
}
/* Get only 1 size if found */
if ( $size ) {
if ( isset( $sizes[ $size ] ) ) {
return $sizes[ $size ];
} else {
return false;
}
}
/**
* Filters array of image sizes.
*
* @since 2.0.0
*
* @param array $sizes Image sizes
*/
return apply_filters( 'tptn_get_all_image_sizes', $sizes );
}

View File

@@ -0,0 +1,378 @@
<?php
/**
* Generates the output
*
* @package Top_Ten
* @author Ajay D'Souza <me@ajaydsouza.com>
* @license GPL-2.0+
* @link https://webberzone.com
* @copyright 2009-2015 Ajay D'Souza
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Returns the link attributes.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @param object $result Result object.
* @return string Space separated list of link attributes
*/
function tptn_link_attributes( $args, $result ) {
$rel_attribute = ( $args['link_nofollow'] ) ? ' rel="nofollow" ' : ' ';
$target_attribute = ( $args['link_new_window'] ) ? ' target="_blank" ' : ' ';
$link_attributes = array(
'rel_attribute' => $rel_attribute,
'target_attribute' => $target_attribute,
);
/**
* Filter the title of the popular posts list
*
* @since 2.2.0
*
* @param array $link_attributes Array of link attributes
* @param array $args Array of arguments
*/
$link_attributes = apply_filters( 'tptn_link_attributes', $link_attributes, $args, $result );
// Convert it to a string.
$link_attributes = implode( ' ', $link_attributes );
return $link_attributes;
}
/**
* Returns the heading of the popular posts.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @return string Space separated list of link attributes
*/
function tptn_heading_title( $args ) {
$title = '';
if ( $args['heading'] && ! $args['is_widget'] ) {
$title = $args['daily'] ? $args['title_daily'] : $args['title'];
}
/**
* Filter the title of the Top posts.
*
* @since 1.9.5
*
* @param string $title Title/heading of the popular posts list
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_heading_title', $title, $args );
}
/**
* Returns the opening tag of the popular posts list.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @return string Space separated list of link attributes
*/
function tptn_before_list( $args ) {
$before_list = $args['before_list'];
/**
* Filter the opening tag of the popular posts list
*
* @since 1.9.10.1
*
* @param string $before_list Opening tag set in the Settings Page
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_before_list', $before_list, $args );
}
/**
* Returns the closing tag of the popular posts list.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @return string Space separated list of link attributes
*/
function tptn_after_list( $args ) {
$after_list = $args['after_list'];
/**
* Filter the closing tag of the popular posts list
*
* @since 1.9.10.1
*
* @param string $after_list Closing tag set in the Settings Page
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_after_list', $after_list, $args );
}
/**
* Returns the opening tag of each list item.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @return string Space separated list of link attributes
*/
function tptn_before_list_item( $args, $result ) {
$before_list_item = $args['before_list_item'];
/**
* Filter the opening tag of each list item.
*
* @since 1.9.10.1
*
* @param string $before_list_item Tag before each list item. Can be defined in the Settings page.
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_before_list_item', $before_list_item, $result, $args );
}
/**
* Returns the closing tag of each list item.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @return string Space separated list of link attributes
*/
function tptn_after_list_item( $args, $result ) {
$after_list_item = $args['after_list_item'];
/**
* Filter the closing tag of each list item.
*
* @since 1.9.10.1
*
* @param string $after_list_item Tag after each list item. Can be defined in the Settings page.
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_after_list_item', $after_list_item, $result, $args ); // Pass the post object to the filter.
}
/**
* Returns the title of each list item.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @return string Space separated list of link attributes
*/
function tptn_post_title( $args, $result ) {
$title = tptn_trim_char( get_the_title( $result->ID ), $args['title_length'] ); // Get the post title and crop it if needed.
/**
* Filter the post title of each list item.
*
* @since 2.0.0
*
* @param string $title Title of the post.
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_post_title', $title, $result, $args );
}
/**
* Returns the author of each list item.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @return string Space separated list of link attributes
*/
function tptn_author( $args, $result ) {
$author_info = get_userdata( $result->post_author );
$author_link = ( false === $author_info ) ? '' : get_author_posts_url( $author_info->ID );
$author_name = ( false === $author_info ) ? '' : ucwords( trim( stripslashes( $author_info->display_name ) ) );
/**
* Filter the author name.
*
* @since 1.9.1
*
* @param string $author_name Proper name of the post author.
* @param object $author_info WP_User object of the post author
*/
$author_name = apply_filters( 'tptn_author_name', $author_name, $author_info );
if ( ! empty( $author_name ) ) {
$tptn_author = '<span class="crp_author"> ' . __( ' by ', 'top-10' ) . '<a href="' . $author_link . '">' . $author_name . '</a></span> ';
} else {
$tptn_author = '';
}
/**
* Filter the text with the author details.
*
* @since 2.0.0
*
* @param string $tptn_author Formatted string with author details and link
* @param object $author_info WP_User object of the post author
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_author', $tptn_author, $author_info, $result, $args );
}
/**
* Returns the formatted list item with link and and thumbnail for each list item.
*
* @since 2.2.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @return string Space separated list of link attributes
*/
function tptn_list_link( $args, $result ) {
$output = '';
$title = tptn_post_title( $args, $result );
$link_attributes = tptn_link_attributes( $args, $result );
if ( 'after' === $args['post_thumb_op'] ) {
$output .= '<a href="' . get_permalink( $result->ID ) . '" ' . $link_attributes . ' class="tptn_link">'; // Add beginning of link.
$output .= '<span class="tptn_title">' . $title . '</span>'; // Add title if post thumbnail is to be displayed after.
$output .= '</a>'; // Close the link.
}
if ( 'inline' === $args['post_thumb_op'] || 'after' === $args['post_thumb_op'] || 'thumbs_only' === $args['post_thumb_op'] ) {
$output .= '<a href="' . get_permalink( $result->ID ) . '" ' . $link_attributes . ' class="tptn_link">'; // Add beginning of link.
$output .= tptn_get_the_post_thumbnail(
array(
'postid' => $result,
'thumb_height' => $args['thumb_height'],
'thumb_width' => $args['thumb_width'],
'thumb_meta' => $args['thumb_meta'],
'thumb_html' => $args['thumb_html'],
'thumb_default' => $args['thumb_default'],
'thumb_default_show' => $args['thumb_default_show'],
'scan_images' => $args['scan_images'],
'class' => 'tptn_thumb',
)
);
$output .= '</a>'; // Close the link.
}
if ( 'inline' === $args['post_thumb_op'] || 'text_only' === $args['post_thumb_op'] ) {
$output .= '<span class="tptn_after_thumb">';
$output .= '<a href="' . get_permalink( $result->ID ) . '" ' . $link_attributes . ' class="tptn_link">'; // Add beginning of link.
$output .= '<span class="tptn_title">' . $title . '</span>'; // Add title when required by settings.
$output .= '</a>'; // Close the link.
}
/**
* Filter Formatted list item with link and and thumbnail.
*
* @since 2.2.0
*
* @param string $output Formatted list item with link and and thumbnail
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_list_link', $output, $result, $args );
}
/**
* Returns the title of each list item.
*
* @since 2.6.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @return string Formatted post date
*/
function tptn_date( $args, $result ) {
$date = mysql2date( get_option( 'date_format', 'd/m/y' ), $result->post_date );
/**
* Filter the post title of each list item.
*
* @since 2.6.0
*
* @param string $date Title of the post.
* @param object $result Object of the current post result
* @param array $args Array of arguments
*/
return apply_filters( 'tptn_date', $date, $result, $args );
}
/**
* Returns the title of each list item.
*
* @since 2.6.0
*
* @param array $args Array of arguments.
* @param object $result Object of the current post result.
* @param int $visits Number of visits.
* @return string Formatted post date
*/
function tptn_list_count( $args, $result, $visits ) {
$tptn_list_count = '(' . tptn_number_format_i18n( $visits ) . ')';
/**
* Filter the formatted list count text.
*
* @since 2.1.0
*
* @param string $visits Formatted list count
* @param int $visits Post count
* @param object $result Post object
* @param array $args Array of arguments.
* @param int $visits Number of visits.
*/
return apply_filters( 'tptn_list_count', $tptn_list_count, $visits, $result, $args, $visits );
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Functions dealing with styles.
*
* @package Top_Ten
*/
/**
* Function to add CSS to header.
*
* @since 1.9
*/
function tptn_header() {
$tptn_custom_css = stripslashes( tptn_get_option( 'custom_css' ) );
// Add CSS to header.
if ( '' != $tptn_custom_css ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
echo '<style type="text/css">' . $tptn_custom_css . '</style>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
add_action( 'wp_head', 'tptn_header' );
/**
* Enqueue styles.
*/
function tptn_heading_styles() {
$style_array = tptn_get_style();
if ( ! empty( $style_array['name'] ) ) {
$style = $style_array['name'];
$extra_css = $style_array['extra_css'];
wp_register_style( "tptn-style-{$style}", plugins_url( "css/{$style}.min.css", TOP_TEN_PLUGIN_FILE ), array(), '1.0.1' );
wp_enqueue_style( "tptn-style-{$style}" );
wp_add_inline_style( "tptn-style-{$style}", $extra_css );
}
}
add_action( 'wp_enqueue_scripts', 'tptn_heading_styles' );
/**
* Get the current style for the popular posts.
*
* @since 3.0.0
*
* @return array Contains two elements:
* 'name' holding style name and 'extra_css' to be added inline.
*/
function tptn_get_style() {
$style = array();
$thumb_width = tptn_get_option( 'thumb_width' );
$thumb_height = tptn_get_option( 'thumb_height' );
$tptn_style = tptn_get_option( 'tptn_styles' );
switch ( $tptn_style ) {
case 'left_thumbs':
$style['name'] = 'left-thumbs';
$style['extra_css'] = "
.tptn_related a {
width: {$thumb_width}px;
height: {$thumb_height}px;
text-decoration: none;
}
.tptn_related img {
max-width: {$thumb_width}px;
margin: auto;
}
.tptn_related .tptn_title {
width: 100%;
}
";
break;
default:
$style['name'] = '';
$style['extra_css'] = '';
break;
}
return $style;
}

View File

@@ -0,0 +1,316 @@
<?php
/**
* Functions controlling the tracker
*
* @package Top_Ten
*/
/**
* Enqueues the scripts needed by Top 10.
*
* @since 1.9.7
* @return void
*/
function tptn_enqueue_scripts() {
global $post, $ajax_tptn_tracker;
if ( ! is_object( $post ) ) {
return;
}
$track_users = tptn_get_option( 'track_users' );
$trackers = tptn_get_option( 'trackers' );
if ( ( is_singular() || tptn_get_option( 'tracker_all_pages' ) ) && ( 'draft' !== $post->post_status ) && ! is_customize_preview() ) {
$current_user = wp_get_current_user(); // Let's get the current user.
$post_author = ( $current_user->ID === $post->post_author ) ? true : false; // Is the current user the post author?
$current_user_admin = ( current_user_can( 'manage_options' ) ) ? true : false; // Is the current user an admin?
$current_user_editor = ( ( current_user_can( 'edit_others_posts' ) ) && ( ! current_user_can( 'manage_options' ) ) ) ? true : false; // Is the current user an editor?
$include_code = true;
if ( ( $post_author ) && ( empty( $track_users['authors'] ) ) ) {
$include_code = false;
}
if ( ( $current_user_admin ) && ( empty( $track_users['admins'] ) ) ) {
$include_code = false;
}
if ( ( $current_user_editor ) && ( empty( $track_users['editors'] ) ) ) {
$include_code = false;
}
if ( ( $current_user->exists() ) && ( ! tptn_get_option( 'logged_in' ) ) ) {
$include_code = false;
}
if ( $include_code ) {
$id = is_singular() ? absint( $post->ID ) : 0;
$blog_id = get_current_blog_id();
$activate_counter = ! empty( $trackers['overall'] ) ? 1 : 0; // It's 1 if we're updating the overall count.
$activate_counter = $activate_counter + ( ! empty( $trackers['daily'] ) ? 10 : 0 ); // It's 10 if we're updating the daily count.
$top_ten_debug = absint( tptn_get_option( 'debug_mode' ) );
$tracker_type = tptn_get_option( 'tracker_type' );
switch ( $tracker_type ) {
case 'query_based':
$home_url = home_url( '/' );
break;
case 'ajaxurl':
$home_url = admin_url( 'admin-ajax.php' );
break;
case 'rest_based':
$home_url = rest_url( 'top-10/v1/tracker' );
break;
default:
$home_url = rest_url( 'top-10/v1/tracker' );
break;
}
/**
* Filter the URL of the tracker.
*
* Other tracker types can override the URL processed by the jQuery.post request
* The corresponding tracker can use the below variables or append their own to $ajax_tptn_tracker
*
* @since 2.0
*/
$home_url = apply_filters( 'tptn_add_counter_script_url', $home_url );
// Strip any query strings since we don't need them.
$home_url = strtok( $home_url, '?' );
$ajax_tptn_tracker = array(
'ajax_url' => $home_url,
'top_ten_id' => $id,
'top_ten_blog_id' => $blog_id,
'activate_counter' => $activate_counter,
'top_ten_debug' => $top_ten_debug,
'tptn_rnd' => wp_rand( 1, time() ),
);
/**
* Filter the localize script arguments for the Top 10 tracker.
*
* @since 2.4.0
*/
$ajax_tptn_tracker = apply_filters( 'tptn_tracker_script_args', $ajax_tptn_tracker );
wp_enqueue_script( 'tptn_tracker', plugins_url( 'includes/js/top-10-tracker.min.js', TOP_TEN_PLUGIN_FILE ), array( 'jquery' ), '1.0', true );
wp_localize_script( 'tptn_tracker', 'ajax_tptn_tracker', $ajax_tptn_tracker );
}
}
}
add_action( 'wp_enqueue_scripts', 'tptn_enqueue_scripts' );
/**
* Function to add additional queries to query_vars.
*
* @since 2.0.0
*
* @param array $vars Query variables array.
* @return array Query variables array with Top 10 parameters appended
*/
function tptn_query_vars( $vars ) {
// Add these to the list of queryvars that WP gathers.
$vars[] = 'top_ten_id';
$vars[] = 'top_ten_blog_id';
$vars[] = 'activate_counter';
$vars[] = 'view_counter';
$vars[] = 'top_ten_debug';
/**
* Function to add additional queries to query_vars.
*
* @since 2.6.0
*
* @param array $vars Updated Query variables array with Top 10 queries added.
*/
return apply_filters( 'tptn_query_vars', $vars );
}
add_filter( 'query_vars', 'tptn_query_vars' );
/**
* Parses the WordPress object to update/display the count.
*
* @since 2.0.0
*
* @param object $wp WordPress object.
*/
function tptn_parse_request( $wp ) {
if ( empty( $wp ) ) {
global $wp;
}
if ( ! isset( $wp->query_vars ) || ! is_array( $wp->query_vars ) ) {
return;
}
if ( array_key_exists( 'top_ten_id', $wp->query_vars ) && empty( $wp->query_vars['top_ten_id'] ) ) {
exit;
}
if ( array_key_exists( 'top_ten_id', $wp->query_vars ) && array_key_exists( 'activate_counter', $wp->query_vars ) && ! empty( $wp->query_vars['top_ten_id'] ) ) {
$id = absint( $wp->query_vars['top_ten_id'] );
$blog_id = absint( $wp->query_vars['top_ten_blog_id'] );
$activate_counter = absint( $wp->query_vars['activate_counter'] );
$str = tptn_update_count( $id, $blog_id, $activate_counter );
// If the debug parameter is set then we output $str else we send a No Content header.
if ( array_key_exists( 'top_ten_debug', $wp->query_vars ) && 1 === absint( $wp->query_vars['top_ten_debug'] ) ) {
header( 'content-type: application/x-javascript' );
wp_send_json( $str );
} else {
header( 'HTTP/1.0 204 No Content' );
header( 'Cache-Control: max-age=15, s-maxage=0' );
}
// Stop anything else from loading as it is not needed.
exit;
} elseif ( array_key_exists( 'top_ten_id', $wp->query_vars ) && array_key_exists( 'view_counter', $wp->query_vars ) && ! empty( $wp->query_vars['top_ten_id'] ) ) {
$id = absint( $wp->query_vars['top_ten_id'] );
if ( $id > 0 ) {
$output = get_tptn_post_count( $id );
header( 'content-type: application/x-javascript' );
echo 'document.write("' . $output . '");'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// Stop anything else from loading as it is not needed.
exit;
}
} else {
return;
}
}
add_action( 'parse_request', 'tptn_parse_request' );
/**
* Parse the ajax response.
*
* @since 2.4.0
*/
function tptn_tracker_parser() {
$id = isset( $_POST['top_ten_id'] ) ? absint( sanitize_text_field( wp_unslash( $_POST['top_ten_id'] ) ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
$blog_id = isset( $_POST['top_ten_blog_id'] ) ? absint( sanitize_text_field( wp_unslash( $_POST['top_ten_blog_id'] ) ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
$activate_counter = isset( $_POST['activate_counter'] ) ? absint( sanitize_text_field( wp_unslash( $_POST['activate_counter'] ) ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
$top_ten_debug = isset( $_POST['top_ten_debug'] ) ? absint( sanitize_text_field( wp_unslash( $_POST['top_ten_debug'] ) ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Missing
$str = tptn_update_count( $id, $blog_id, $activate_counter );
// If the debug parameter is set then we output $str else we send a No Content header.
if ( 1 === $top_ten_debug ) {
echo esc_html( $str );
} else {
header( 'HTTP/1.0 204 No Content' );
header( 'Cache-Control: max-age=15, s-maxage=0' );
}
wp_die();
}
add_action( 'wp_ajax_nopriv_tptn_tracker', 'tptn_tracker_parser' );
add_action( 'wp_ajax_tptn_tracker', 'tptn_tracker_parser' );
/**
* Function to update the count in the database.
*
* @since 2.6.0
*
* @param int $id Post ID.
* @param int $blog_id Blog ID.
* @param int $activate_counter Activate counter flag.
*
* @return string Response on database update.
*/
function tptn_update_count( $id, $blog_id, $activate_counter ) {
global $wpdb;
$table_name = $wpdb->base_prefix . 'top_ten';
$top_ten_daily = $wpdb->base_prefix . 'top_ten_daily';
$str = '';
if ( $id > 0 ) {
if ( ( 1 === $activate_counter ) || ( 11 === $activate_counter ) ) {
$tt = $wpdb->query( $wpdb->prepare( "INSERT INTO {$table_name} (postnumber, cntaccess, blog_id) VALUES( %d, '1', %d ) ON DUPLICATE KEY UPDATE cntaccess= cntaccess+1 ", $id, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$str .= ( false === $tt ) ? 'tte' : 'tt' . $tt;
}
if ( ( 10 === $activate_counter ) || ( 11 === $activate_counter ) ) {
$current_date = current_time( 'Y-m-d H' );
$ttd = $wpdb->query( $wpdb->prepare( "INSERT INTO {$top_ten_daily} (postnumber, cntaccess, dp_date, blog_id) VALUES( %d, '1', %s, %d ) ON DUPLICATE KEY UPDATE cntaccess= cntaccess+1 ", $id, $current_date, $blog_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$str .= ( false === $ttd ) ? ' ttde' : ' ttd' . $ttd;
}
}
/**
* Filter the response on database update.
*
* @since 2.6.0
*
* @param string $str Response string.
* @param int $id Post ID.
* @param int $blog_id Blog ID.
* @param int $activate_counter Activate counter flag.
*/
return apply_filters( 'tptn_update_count', $str, $id, $blog_id, $activate_counter );
}
/**
* Function returns the different types of trackers.
*
* @since 2.4.0
* @return array Tracker types.
*/
function tptn_get_tracker_types() {
$trackers = array(
array(
'id' => 'rest_based',
'name' => __( 'REST API based', 'top-10' ),
'description' => __( 'Uses the REST API to record visits', 'top-10' ),
),
array(
'id' => 'query_based',
'name' => __( 'Query variable based', 'top-10' ),
'description' => __( 'Uses query variables to record visits', 'top-10' ),
),
array(
'id' => 'ajaxurl',
'name' => __( 'Ajaxurl based', 'top-10' ),
'description' => __( 'Uses admin-ajax.php which is inbuilt within WordPress to process the tracker', 'top-10' ),
),
);
/**
* Filter the array containing the types of trackers to add your own.
*
* @since 2.4.0
*
* @param string $trackers Different trackers.
*/
return apply_filters( 'tptn_get_tracker_types', $trackers );
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden

View File

@@ -0,0 +1 @@
<?php // Silence is golden

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<ruleset name="WordPress Coding Standards for Plugins">
<description>Generally-applicable sniffs for WordPress plugins</description>
<exclude-pattern>*/node_modules/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>
<exclude-pattern>*/tests/*</exclude-pattern>
<exclude-pattern>*/index.php</exclude-pattern>
<rule ref="WordPress" />
<!-- Add in some extra rules from other standards. -->
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
<rule ref="Generic.Commenting.Todo"/>
<rule ref="Generic.WhiteSpace.DisallowSpaceIndent.SpacesUsed"/>
</ruleset>

View File

@@ -0,0 +1,164 @@
=== Top 10 - Popular posts plugin for WordPress ===
Tags: popular posts, top 10, counter, top posts, daily popular, page views, statistics, tracker
Contributors: webberzone, Ajay
Donate link: https://ajaydsouza.com/donate/
Stable tag: 3.0.0
Requires at least: 5.0
Tested up to: 5.8
Requires PHP: 5.6
License: GPLv2 or later
Track daily and total visits on your blog posts. Display the count as well as popular and trending posts.
== Description ==
WordPress doesn't have an in-built system to track page views or displaying popular posts. [Top 10](https://webberzone.com/plugins/top-10/) is an easy to use, yet, powerful WordPress plugin that will count the number of page views of your posts, pages and any custom post types. You can then display the page view counts as well as display your most popular posts.
Top 10 adds two widgets that you can use to display a list of popular posts and the counta cross all your blog posts.
Although several similar plugins exist today, Top 10 is one of the most feature-rich popular post plugins with support for thumbnails, shortcodes, widgets, custom post types and CSS styles. The inbuilt caching system also helps reduce server load by caching your popular posts output. The tracking uses ajax and is thus compatible with most popular caching plugins.
Top 10 also has powerful API and is fully extendable with WordPress actions and filters to allow you easily extend the code base to add new features or tweak existing ones.
= Features =
* **Page counter**: Counts page views on single posts, pages and *custom post types* on an hourly basis which can then be easily displayed automatically, using shortcodes or functions
* **Popular posts**: Display a list of popular posts either for total counts or for a custom period. You can choose how many posts are to be displayed along with loads of other customisation options
* **Gutenberg / Block Editor support**: You can find a block called "Popular Posts [Top 10]" with its own configurable set of options
* **Widget ready**: Sidebar widgets available for daily popular and overall popular posts. Highly customizable widgets to control what you want to display in the list of posts
* **Shortcodes**: The plugin includes two shortcodes `[tptn_list]` and `[tptn_views]` to display the posts list and the number of views respectively
* **Thumbnail support**
* Support for WordPress post thumbnails. Top 10 will create a custom image size (`tptn_thumbnail`) with the dimensions specified in the Settings page
* Auto-extract the first image in your post to be displayed as a thumbnail
* Manually enter the URL of the thumbnail via [WordPress meta fields](http://codex.wordpress.org/Custom_Fields). Specify this using the meta box in your Edit screens.
* **Exclusions**: Exclude posts from select categories from appearing in the top posts list. Also exclude posts by ID from appearing in the list
* **Styles**: The output is wrapped in CSS classes which allows you to easily style the list. You can enter your custom CSS styles from within WordPress Admin area or use the style included.
* **Admin interface**: View list of daily and/or overall popular posts from within the dashboard. Top 10 also adds two sortable columns to your All Posts and All Pages pages in your WordPress Admin area
* **Export/Import interface**: Export the count tables and settings to restore in the same site or on other installs
* **Works with caching plugins** like WP-Super-Cache, W3 Total Cache or Quick Cache
* **Extendable code**: Top 10 has tonnes of filters and actions that allow any developer to easily add features, edit outputs, etc.
= GDPR =
Top 10 is GDPR compliant as it doesn't collect any personal data about your visitors when installed out of the box. You can see the data the plugin stores in the `wp_top_ten` and `wp_top_ten_daily` tables in the database. Note: the prefix `wp` might be different if you have changed it from the default.
YOU ARE RESPONSIBLE FOR ENSURING THAT ALL GDPR REQUIREMENTS ARE MET ON YOUR WEBSITE.
= Donations =
I spend a significant amount of my free time maintaining, updating and more importantly supporting this plugin. If you have been using this plugin and find this useful, do consider making a donation. This helps me pay for my hosting and domains.
= Translations =
Top 10 is available for [translation directly on WordPress.org](https://translate.wordpress.org/projects/wp-plugins/top-10). Check out the official [Translator Handbook](https://make.wordpress.org/polyglots/handbook/rosetta/theme-plugin-directories/) to contribute.
= Contribute =
Top 10 is also available on [Github](https://github.com/ajaydsouza/top-10)
So, if you've got some cool feature that you'd like to implement into the plugin or a bug you've been able to fix, consider forking the project and sending me a pull request. Please don't use that for support requests.
== Screenshots ==
1. Top 10 options - General options
2. Top 10 options - Counter and Tracker options
3. Top 10 options - Popular post list options
4. Top 10 options - Thumbnail options
5. Top 10 options - Styles
6. Top 10 options - Maintenance
7. Top 10 options - Feed
8. Top 10 widget options
9. Top 10 Meta box on the Edit Post screen
10. Top 10 Tools page
11. Top 10 - Popular posts view in Admin
12. Top 10 Export/Import interface
13. Top 10 - Popular posts view in Network Admin
14. Top 10 Gutenberg block
== Installation ==
= WordPress install (the easy way) =
1. Navigate to Plugins within your WordPress Admin Area
2. Click "Add new" and in the search box enter "Top 10"
3. Find the plugin in the list (usually the first result) and click "Install Now"
= Manual install =
1. Download the plugin
2. Extract the contents of top-10.zip to wp-content/plugins/ folder. You should get a folder called top-10.
3. Activate the Plugin in WP-Admin.
4. Go to **Top 10 &raquo; Settings** to configure
5. Go to **Appearance &raquo; Widgets** to add the Popular Posts sidebar widget to your theme
6. Go to **Top 10 &raquo; View Popular Posts** to view the list of popular posts
== Frequently Asked Questions ==
Check out the [FAQ on the plugin page](http://wordpress.org/plugins/top-10/faq/) and the [FAQ on the WebberZone knowledgebase](https://webberzone.com/support/section/top-10/).
It is the fastest way to get support as I monitor the forums regularly. I also provide [*paid* premium support via email](https://webberzone.com/support/).
= How can I customise the output? =
Details on how to use and customize the output is in this [knowledge base article](https://webberzone.com/support/knowledgebase/using-and-customising-top-10/)
= Shortcodes =
You can find details of the shortcodes in this [knowledge base article](https://webberzone.com/support/knowledgebase/top-10-shortcodes/)
= Can this plugin replace Google Analytics? =
No. Top 10 has been designed to only track the number of page-views on your blog posts and display the same. It isn't designed to replace Google Analytics or any other full fledged analytics application.
= How does the scheduled maintenance work? =
When you enabled the scheduled maintenance, Top 10 will create a cron job that will run at a predefined interval and clean up old entries from the `wp_top_ten_daily` table.
*Note: If you enable this option, WordPress will execute this job when it is scheduled the first time*
= How to make the columns on the Custom Post Type admin pages sortable? =
Add the following code to your functions.php file of your theme.
`
add_filter( 'manage_edit-{$cpt}_sortable_columns', 'tptn_column_register_sortable' );
`
Replace `{$cpt}` by the slug of your custom post type. E.g. to make the columns on your 'projects' post type sortable, you will need to add:
`
add_filter( 'manage_edit-projects_sortable_columns', 'tptn_column_register_sortable' );
`
== Changelog ==
= 3.0.0 =
Release post: [https://webberzone.com/blog/top-10-v3-0-0/](https://webberzone.com/blog/top-10-v3-0-0/)
* Features:
* New Top_Ten_Query class for fetching popular posts. Adds the function `get_tptn_posts()` which replaces `get_tptn_pop_posts()` which will be deprecated in a future version
* New option to exclude the Front page and Posts page if these are set in Settings > Reading or via Customizer
* New option in the Widget to include specific post IDs in the top lists. You can also use them in the shortcode using `include_post_ids`
* New block for Gutenberg aka the block editor. The block is called **Popular Posts [Top 10]** and you can find it under the widgets category
* Top 10 now supports the WP REST API. The plugin adds a new tracker type called *REST API based* which you can find under Counter/Tracker settings. Additionally, you can now receive the popular posts via a REST Request to `top-10/v1/popular-posts`
* Enhancements/Modifications:
* No popular posts feed will be added if the corresponding slug is set to blank
* Changed `sum_count` to `visits`
* Bug fixes:
* PHP notices when displaying Network Wide Popular Posts in WordPress Multisite
* Query based tracker gave an ajax error
For previous changelog entries, please refer to the separate changelog.txt file or [Github Releases page](https://github.com/WebberZone/top-10/releases)
== Upgrade Notice ==
= 3.0.0 =
Major release; Please check the plugin settings; Read all details in the release post

View File

@@ -0,0 +1,186 @@
<?php
/**
* Top 10.
*
* Count daily and total visits per post and display the most popular posts based on the number of views.
*
* @package Top_Ten
* @author Ajay D'Souza <me@ajaydsouza.com>
* @license GPL-2.0+
* @link https://webberzone.com
* @copyright 2008-2021 Ajay D'Souza
*
* @wordpress-plugin
* Plugin Name: Top 10
* Plugin URI: https://webberzone.com/plugins/top-10/
* Description: Count daily and total visits per post and display the most popular posts based on the number of views
* Version: 3.0.0
* Author: Ajay D'Souza
* Author URI: https://webberzone.com
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: top-10
* Domain Path: /languages
* GitHub Plugin URI: https://github.com/WebberZone/top-10/
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
/**
* Holds the filesystem directory path (with trailing slash) for Top 10
*
* @since 2.3.0
*
* @var string Plugin folder path
*/
if ( ! defined( 'TOP_TEN_PLUGIN_DIR' ) ) {
define( 'TOP_TEN_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
}
/**
* Holds the filesystem directory path (with trailing slash) for Top 10
*
* @since 2.3.0
*
* @var string Plugin folder URL
*/
if ( ! defined( 'TOP_TEN_PLUGIN_URL' ) ) {
define( 'TOP_TEN_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
}
/**
* Holds the filesystem directory path (with trailing slash) for Top 10
*
* @since 2.3.0
*
* @var string Plugin Root File
*/
if ( ! defined( 'TOP_TEN_PLUGIN_FILE' ) ) {
define( 'TOP_TEN_PLUGIN_FILE', __FILE__ );
}
/**
* Number of days of data to be saved in the daily tables.
*
* @since 3.0.0
*
* @var int Number of days of data to be saved in the daily tables.
*/
if ( ! defined( 'TOP_TEN_STORE_DATA' ) ) {
define( 'TOP_TEN_STORE_DATA', 180 );
}
/**
* Global variable holding the current database version of Top 10
*
* @since 1.0
*
* @var string
*/
global $tptn_db_version;
$tptn_db_version = '6.0';
/**
* Global variable holding the current settings for Top 10
*
* @since 1.9.3
*
* @var array
*/
global $tptn_settings;
$tptn_settings = tptn_get_settings();
/**
* Get Settings.
*
* Retrieves all plugin settings
*
* @since 2.5.0
* @return array Top 10 settings
*/
function tptn_get_settings() {
$settings = get_option( 'tptn_settings' );
/**
* Settings array
*
* Retrieves all plugin settings
*
* @since 1.2.0
* @param array $settings Settings array
*/
return apply_filters( 'tptn_get_settings', $settings );
}
/*
*---------------------------------------------------------------------------*
* Top 10 modules
*---------------------------------------------------------------------------*
*/
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/default-settings.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/register-settings.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/activate-deactivate.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/class-top-ten-query.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/public/display-posts.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/public/styles.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/public/output-generator.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/public/media.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/l10n.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/counter.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/tracker.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/cron.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/helpers.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/formatting.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/modules/shortcode.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/modules/exclusions.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/modules/taxonomies.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/modules/class-top-ten-widget.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/modules/class-top-ten-count-widget.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/modules/class-top-ten-rest-api.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/blocks/popular-posts.php';
/*
*---------------------------------------------------------------------------*
* Dashboard and Administrative Functionality
*---------------------------------------------------------------------------*
*/
if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/admin.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/class-top-ten-dashboard.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/settings-page.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/save-settings.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/help-tab.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/tools.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/import-export.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/admin-metabox.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/admin-columns.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/admin-dashboard.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/class-top-ten-statistics.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/class-top-ten-statistics-table.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/class-top-ten-network-statistics.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/class-top-ten-network-statistics-table.php';
require_once TOP_TEN_PLUGIN_DIR . 'includes/admin/cache.php';
} // End admin.inc
/*
*---------------------------------------------------------------------------*
* Deprecated functions
*---------------------------------------------------------------------------*
*/
require_once TOP_TEN_PLUGIN_DIR . 'includes/deprecated.php';

View File

@@ -0,0 +1,43 @@
<?php
/**
* Update counts to database.
*
* @package Top_Ten
*/
// If this file is called directly, abort.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
die;
}
global $wpdb;
$tptn_settings = get_option( 'tptn_settings' );
if ( $tptn_settings['uninstall_clean_tables'] ) {
$table_name = $wpdb->base_prefix . 'top_ten';
$table_name_daily = $wpdb->base_prefix . 'top_ten_daily';
$wpdb->query( "DROP TABLE $table_name" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
$wpdb->query( "DROP TABLE $table_name_daily" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery
delete_option( 'tptn_db_version' );
}
if ( $tptn_settings['uninstall_clean_options'] ) {
if ( wp_next_scheduled( 'tptn_cron_hook' ) ) {
wp_clear_scheduled_hook( 'tptn_cron_hook' );
}
delete_option( 'ald_tptn_settings' );
delete_option( 'tptn_settings' );
$wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
"
DELETE FROM {$wpdb->options}
WHERE option_name LIKE '%tptn%'
"
);
}