Simple Download Monitor - Version 3.3.4

Version Description

  • Replace deprecated get_currentuserinfo() with wp_get_current_user()
  • Improve remote IP and location detection
  • Added a new shortcode to show a simple list of the download categories
  • Fix: avoid undefined variable notices in sdm_pop_cats_ajax_call()
Download this release

Release Info

Developer mra13
Plugin Icon 128x128 Simple Download Monitor
Version 3.3.4
Comparing to
See all releases

Code changes from version 3.3.2 to 3.3.4

includes/sdm-download-request-handler.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ //Handles the download request
4
+ function handle_sdm_download_via_direct_post() {
5
+ if (isset($_REQUEST['smd_process_download']) && $_REQUEST['smd_process_download'] == '1') {
6
+ global $wpdb;
7
+ $download_id = absint($_REQUEST['download_id']);
8
+ $download_title = get_the_title($download_id);
9
+ $download_link = get_post_meta($download_id, 'sdm_upload', true);
10
+
11
+ //Do some validation checks
12
+ if ( !$download_id ) {
13
+ wp_die(__('Error! Incorrect download item id.', 'simple-download-monitor'));
14
+ }
15
+ if (empty($download_link)) {
16
+ wp_die(__('Error! This download item (' . $download_id . ') does not have any download link. Edit this item and specify a downloadable file URL for it.', 'simple-download-monitor'));
17
+ }
18
+
19
+ //Check download password (if applicable for this download)
20
+ $post_object = get_post($download_id);// Get post object
21
+ $post_pass = $post_object->post_password;// Get post password
22
+ if(!empty($post_pass)){//This download item has a password. So validate the password.
23
+ $pass_val = $_REQUEST['pass_text'];
24
+ if(empty($pass_val)){//No password was submitted with the downoad request.
25
+ wp_die(__('Error! This download requires a password.', 'simple-download-monitor'));
26
+ }
27
+ if ($post_pass != $pass_val) {
28
+ //Incorrect password submitted.
29
+ wp_die(__('Error! Incorrect password. This download requires a valid password.', 'simple-download-monitor'));
30
+ } else {
31
+ //Password is valid. Go ahead with the download
32
+ }
33
+ }
34
+ //End of password check
35
+
36
+ $ipaddress = sdm_get_ip_address();
37
+ $date_time = current_time('mysql');
38
+ $visitor_country = $ipaddress ? sdm_ip_info($ipaddress, 'country') : '';
39
+
40
+ if (is_user_logged_in()) { // Get user name (if logged in)
41
+ $current_user = wp_get_current_user();
42
+ $visitor_name = $current_user->user_login;
43
+ } else {
44
+ $visitor_name = __('Not Logged In', 'simple-download-monitor');
45
+ }
46
+
47
+ // Get option for global disabling of download logging
48
+ $main_option = get_option('sdm_downloads_options');
49
+ $no_logs = isset($main_option['admin_no_logs']);
50
+
51
+ // Get optoin for logging only unique IPs
52
+ $unique_ips = isset($main_option['admin_log_unique']);
53
+
54
+ // Get post meta for individual disabling of download logging
55
+ $get_meta = get_post_meta($download_id, 'sdm_item_no_log', true);
56
+ $item_logging_checked = isset($get_meta) && $get_meta === 'on' ? 'on' : 'off';
57
+
58
+ $dl_logging_needed = true;
59
+
60
+ // Check if download logs have been disabled (globally or per download item)
61
+ if ($no_logs === true || $item_logging_checked === 'on') {
62
+ $dl_logging_needed = false;
63
+ }
64
+
65
+ // Check if we are only logging unique ips
66
+ if ($unique_ips === true) {
67
+ $check_ip = $wpdb->get_results('SELECT * FROM ' . $wpdb->prefix . 'sdm_downloads WHERE post_id="' . $download_id . '" AND visitor_ip = "' . $ipaddress . '"');
68
+
69
+ //This IP is already logged for this download item. No need to log it again.
70
+ if ($check_ip) {
71
+ $dl_logging_needed = false;
72
+ }
73
+ }
74
+
75
+ if ($dl_logging_needed) {
76
+ // We need to log this download.
77
+ $table = $wpdb->prefix . 'sdm_downloads';
78
+ $data = array(
79
+ 'post_id' => $download_id,
80
+ 'post_title' => $download_title,
81
+ 'file_url' => $download_link,
82
+ 'visitor_ip' => $ipaddress,
83
+ 'date_time' => $date_time,
84
+ 'visitor_country' => $visitor_country,
85
+ 'visitor_name' => $visitor_name
86
+ );
87
+
88
+ $data = array_filter($data); //Remove any null values.
89
+ $insert_table = $wpdb->insert($table, $data);
90
+
91
+ if ($insert_table) {
92
+ //Download request was logged successfully
93
+ } else {
94
+ //Failed to log the download request
95
+ wp_die(__('Error! Failed to log the download request in the database table', 'simple-download-monitor'));
96
+ }
97
+ }
98
+
99
+ // Should the item be dispatched?
100
+ $dispatch = apply_filters('sdm_dispatch_downloads', get_post_meta($download_id, 'sdm_item_dispatch', true));
101
+
102
+ // Only local file can be dispatched.
103
+ if ( $dispatch && (stripos($download_link, WP_CONTENT_URL) === 0) ) {
104
+ // Get file path
105
+ $file = path_join(WP_CONTENT_DIR, ltrim(substr($download_link, strlen(WP_CONTENT_URL)), '/'));
106
+ // Try to dispatch file (terminates script execution on success)
107
+ sdm_dispatch_file($file);
108
+ }
109
+
110
+ // As a fallback or when dispatching is disabled, redirect to the file
111
+ // (and terminate script execution).
112
+ sdm_redirect_to_url($download_link);
113
+ }
114
+ }
115
+
116
+ /*
117
+ * Use this function to redirect to a URL
118
+ */
119
+ function sdm_redirect_to_url($url, $delay = '0', $exit = '1') {
120
+ $url = apply_filters('sdm_before_redirect_to_url',$url);
121
+ if (empty($url)) {
122
+ echo '<strong>';
123
+ _e('Error! The URL value is empty. Please specify a correct URL value to redirect to!', 'simple-download-monitor');
124
+ echo '</strong>';
125
+ exit;
126
+ }
127
+ if (!headers_sent()) {
128
+ header('Location: ' . $url);
129
+ } else {
130
+ echo '<meta http-equiv="refresh" content="' . $delay . ';url=' . $url . '" />';
131
+ }
132
+ if ($exit == '1') {//exit
133
+ exit;
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Dispatch file with $filename and terminate script execution, if the file is
139
+ * readable and headers have not been sent yet.
140
+ * @param string $filename
141
+ * @return void
142
+ */
143
+ function sdm_dispatch_file($filename) {
144
+
145
+ if ( headers_sent() ) {
146
+ trigger_error(__FUNCTION__ . ": Cannot dispatch file $filename, headers already sent.");
147
+ return;
148
+ }
149
+
150
+ if ( !is_readable($filename) ) {
151
+ trigger_error(__FUNCTION__ . ": Cannot dispatch file $filename, file is not readable.");
152
+ return;
153
+ }
154
+
155
+ header('Content-Description: File Transfer');
156
+ header('Content-Type: application/octet-stream'); // http://stackoverflow.com/a/20509354
157
+ header('Content-Disposition: attachment; filename="'.basename($filename).'"');
158
+ header('Expires: 0');
159
+ header('Cache-Control: must-revalidate');
160
+ header('Pragma: public');
161
+ header('Content-Length: ' . filesize($filename));
162
+
163
+ ob_end_clean();
164
+ readfile($filename);
165
+ exit;
166
+ }
includes/sdm-utility-functions.php CHANGED
@@ -45,39 +45,38 @@ function sdm_get_password_entry_form($id) {
45
  return $data;
46
  }
47
 
48
- //Use this function to redirect to a URL
49
- function sdm_redirect_to_url($url, $delay = '0', $exit = '1') {
50
- $url = apply_filters('sdm_before_redirect_to_url',$url);
51
- if (empty($url)) {
52
- echo '<strong>';
53
- _e('Error! The URL value is empty. Please specify a correct URL value to redirect to!', 'simple-download-monitor');
54
- echo '</strong>';
55
- exit;
56
- }
57
- if (!headers_sent()) {
58
- header('Location: ' . $url);
59
- } else {
60
- echo '<meta http-equiv="refresh" content="' . $delay . ';url=' . $url . '" />';
61
- }
62
- if ($exit == '1') {//exit
63
- exit;
64
- }
65
- }
66
 
67
- // Helper function to get visitor country (or other info)
68
- function sdm_ip_info($ip = NULL, $purpose = "location", $deep_detect = TRUE) {
69
- $output = NULL;
70
- if (filter_var($ip, FILTER_VALIDATE_IP) === FALSE) {
71
- $ip = $_SERVER["REMOTE_ADDR"];
72
- if ($deep_detect) {
73
- if (filter_var(@$_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP))
74
- $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
75
- if (filter_var(@$_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP))
76
- $ip = $_SERVER['HTTP_CLIENT_IP'];
 
 
 
 
 
 
 
 
77
  }
78
  }
79
- $purpose = str_replace(array("name", "\n", "\t", " ", "-", "_"), NULL, strtolower(trim($purpose)));
80
- $support = array("country", "countrycode", "state", "region", "city", "location", "address");
 
 
 
 
 
 
 
 
 
81
  $continents = array(
82
  "AF" => "Africa",
83
  "AN" => "Antarctica",
@@ -87,47 +86,42 @@ function sdm_ip_info($ip = NULL, $purpose = "location", $deep_detect = TRUE) {
87
  "NA" => "North America",
88
  "SA" => "South America"
89
  );
90
- if (filter_var($ip, FILTER_VALIDATE_IP) && in_array($purpose, $support)) {
91
- $ipdat = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip));
92
- if (@strlen(trim($ipdat->geoplugin_countryCode)) == 2) {
93
- switch ($purpose) {
94
- case "location":
95
- $output = array(
96
- "city" => @$ipdat->geoplugin_city,
97
- "state" => @$ipdat->geoplugin_regionName,
98
- "country" => @$ipdat->geoplugin_countryName,
99
- "country_code" => @$ipdat->geoplugin_countryCode,
100
- "continent" => @$continents[strtoupper($ipdat->geoplugin_continentCode)],
101
- "continent_code" => @$ipdat->geoplugin_continentCode
102
- );
103
- break;
104
- case "address":
105
- $address = array($ipdat->geoplugin_countryName);
106
- if (@strlen($ipdat->geoplugin_regionName) >= 1)
107
- $address[] = $ipdat->geoplugin_regionName;
108
- if (@strlen($ipdat->geoplugin_city) >= 1)
109
- $address[] = $ipdat->geoplugin_city;
110
- $output = implode(", ", array_reverse($address));
111
- break;
112
- case "city":
113
- $output = @$ipdat->geoplugin_city;
114
- break;
115
- case "state":
116
- $output = @$ipdat->geoplugin_regionName;
117
- break;
118
- case "region":
119
- $output = @$ipdat->geoplugin_regionName;
120
- break;
121
- case "country":
122
- $output = @$ipdat->geoplugin_countryName;
123
- break;
124
- case "countrycode":
125
- $output = @$ipdat->geoplugin_countryCode;
126
- break;
127
- }
128
  }
129
  }
130
- return $output;
 
 
131
  }
132
 
133
  /*
45
  return $data;
46
  }
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
 
49
+ /**
50
+ * Get remote IP address.
51
+ * @link http://stackoverflow.com/questions/1634782/what-is-the-most-accurate-way-to-retrieve-a-users-correct-ip-address-in-php
52
+ *
53
+ * @param bool $ignore_private_and_reserved Ignore IPs that fall into private or reserved IP ranges.
54
+ * @return mixed IP address as a string or null, if remote IP address cannot be determined (or is ignored).
55
+ */
56
+ function sdm_get_ip_address($ignore_private_and_reserved = false) {
57
+ $flags = $ignore_private_and_reserved ? (FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) : 0;
58
+ foreach ( array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key ) {
59
+ if ( array_key_exists($key, $_SERVER) === true ) {
60
+ foreach ( explode(',', $_SERVER[$key]) as $ip ) {
61
+ $ip = trim($ip); // just to be safe
62
+
63
+ if ( filter_var($ip, FILTER_VALIDATE_IP, $flags) !== false ) {
64
+ return $ip;
65
+ }
66
+ }
67
  }
68
  }
69
+ return null;
70
+ }
71
+
72
+ /**
73
+ * Get location information (country or other info) for given IP address.
74
+ * @param string $ip
75
+ * @param string $purpose
76
+ * @return mixed
77
+ */
78
+ function sdm_ip_info($ip, $purpose = "location") {
79
+
80
  $continents = array(
81
  "AF" => "Africa",
82
  "AN" => "Antarctica",
86
  "NA" => "North America",
87
  "SA" => "South America"
88
  );
89
+
90
+ $ipdat = @json_decode(file_get_contents("http://www.geoplugin.net/json.gp?ip=" . $ip));
91
+
92
+ if (@strlen(trim($ipdat->geoplugin_countryCode)) === 2) {
93
+ switch ($purpose) {
94
+ case "location":
95
+ return array(
96
+ "city" => @$ipdat->geoplugin_city,
97
+ "state" => @$ipdat->geoplugin_regionName,
98
+ "country" => @$ipdat->geoplugin_countryName,
99
+ "country_code" => @$ipdat->geoplugin_countryCode,
100
+ "continent" => @$continents[strtoupper($ipdat->geoplugin_continentCode)],
101
+ "continent_code" => @$ipdat->geoplugin_continentCode
102
+ );
103
+ case "address":
104
+ $address = array($ipdat->geoplugin_countryName);
105
+ if (@strlen($ipdat->geoplugin_regionName) >= 1)
106
+ $address[] = $ipdat->geoplugin_regionName;
107
+ if (@strlen($ipdat->geoplugin_city) >= 1)
108
+ $address[] = $ipdat->geoplugin_city;
109
+ return implode(", ", array_reverse($address));
110
+ case "city":
111
+ return @$ipdat->geoplugin_city;
112
+ case "state":
113
+ return @$ipdat->geoplugin_regionName;
114
+ case "region":
115
+ return @$ipdat->geoplugin_regionName;
116
+ case "country":
117
+ return @$ipdat->geoplugin_countryName;
118
+ case "countrycode":
119
+ return @$ipdat->geoplugin_countryCode;
 
 
 
 
 
 
 
120
  }
121
  }
122
+
123
+ // Either no info found or invalid $purpose.
124
+ return null;
125
  }
126
 
127
  /*
main.php CHANGED
@@ -3,7 +3,7 @@
3
  * Plugin Name: Simple Download Monitor
4
  * Plugin URI: https://www.tipsandtricks-hq.com/simple-wordpress-download-monitor-plugin
5
  * Description: Easily manage downloadable files and monitor downloads of your digital files from your WordPress site.
6
- * Version: 3.3.2
7
  * Author: Tips and Tricks HQ, Ruhul Amin, Josh Lobe
8
  * Author URI: https://www.tipsandtricks-hq.com/development-center
9
  * License: GPL2
@@ -12,7 +12,7 @@ if (!defined('ABSPATH')) {
12
  exit;
13
  }
14
 
15
- define('WP_SIMPLE_DL_MONITOR_VERSION', '3.3.2');
16
  define('WP_SIMPLE_DL_MONITOR_DIR_NAME', dirname(plugin_basename(__FILE__)));
17
  define('WP_SIMPLE_DL_MONITOR_URL', plugins_url('', __FILE__));
18
  define('WP_SIMPLE_DL_MONITOR_PATH', plugin_dir_path(__FILE__));
@@ -24,6 +24,7 @@ $sdm_db_version = '1.2';
24
  //File includes
25
  include_once('includes/sdm-utility-functions.php');
26
  include_once('includes/sdm-utility-functions-admin-side.php');
 
27
  include_once('includes/sdm-logs-list-table.php');
28
  include_once('includes/sdm-latest-downloads.php');
29
  include_once('sdm-post-type-and-taxonomy.php');
@@ -80,12 +81,14 @@ function sdm_plugins_loaded_tasks() {
80
  * * Handle Generic Init tasks
81
  */
82
  add_action('init', 'sdm_init_time_tasks');
83
-
84
  function sdm_init_time_tasks() {
85
  //Handle download request if any
86
  handle_sdm_download_via_direct_post();
87
  }
88
 
 
 
 
89
  function sdm_db_update_check() {
90
  if (is_admin()) {//Check if DB needs to be upgraded
91
  global $sdm_db_version;
@@ -120,23 +123,24 @@ class simpleDownloadManager {
120
  add_action('init', 'sdm_register_post_type'); // Create 'sdm_downloads' custom post type
121
  add_action('init', 'sdm_create_taxonomies'); // Register 'tags' and 'categories' taxonomies
122
  add_action('init', 'sdm_register_shortcodes'); //Register the shortcodes
123
- add_action('wp_enqueue_scripts', array(&$this, 'sdm_frontend_scripts')); // Register frontend scripts
124
 
125
  if (is_admin()) {
126
- add_action('admin_menu', array(&$this, 'sdm_create_menu_pages')); // Create admin pages
127
- add_action('add_meta_boxes', array(&$this, 'sdm_create_upload_metabox')); // Create metaboxes
128
 
129
- add_action('save_post', array(&$this, 'sdm_save_description_meta_data')); // Save 'description' metabox
130
- add_action('save_post', array(&$this, 'sdm_save_upload_meta_data')); // Save 'upload file' metabox
131
- add_action('save_post', array(&$this, 'sdm_save_thumbnail_meta_data')); // Save 'thumbnail' metabox
132
- add_action('save_post', array(&$this, 'sdm_save_statistics_meta_data')); // Save 'statistics' metabox
133
- add_action('save_post', array(&$this, 'sdm_save_other_details_meta_data')); // Save 'other details' metabox
 
134
 
135
- add_action('admin_enqueue_scripts', array(&$this, 'sdm_admin_scripts')); // Register admin scripts
136
- add_action('admin_print_styles', array(&$this, 'sdm_admin_styles')); // Register admin styles
137
 
138
- add_action('admin_init', array(&$this, 'sdm_register_options')); // Register admin options
139
- //add_filter('post_row_actions', array(&$this, 'sdm_remove_view_link_cpt'), 10, 2); // Remove 'View' link in all downloads list view
140
  }
141
  }
142
 
@@ -206,12 +210,13 @@ class simpleDownloadManager {
206
  public function sdm_create_upload_metabox() {
207
 
208
  //***** Create metaboxes for the custom post type
209
- add_meta_box('sdm_description_meta_box', __('Description', 'simple-download-monitor'), array(&$this, 'display_sdm_description_meta_box'), 'sdm_downloads', 'normal', 'default');
210
- add_meta_box('sdm_upload_meta_box', __('Upload File', 'simple-download-monitor'), array(&$this, 'display_sdm_upload_meta_box'), 'sdm_downloads', 'normal', 'default');
211
- add_meta_box('sdm_thumbnail_meta_box', __('File Thumbnail (Optional)', 'simple-download-monitor'), array(&$this, 'display_sdm_thumbnail_meta_box'), 'sdm_downloads', 'normal', 'default');
212
- add_meta_box('sdm_stats_meta_box', __('Statistics', 'simple-download-monitor'), array(&$this, 'display_sdm_stats_meta_box'), 'sdm_downloads', 'normal', 'default');
213
- add_meta_box('sdm_other_details_meta_box', __('Other Details (Optional)', 'simple-download-monitor'), array(&$this, 'display_sdm_other_details_meta_box'), 'sdm_downloads', 'normal', 'default');
214
- add_meta_box('sdm_shortcode_meta_box', __('Shortcodes', 'simple-download-monitor'), array(&$this, 'display_sdm_shortcode_meta_box'), 'sdm_downloads', 'normal', 'default');
 
215
 
216
  }
217
 
@@ -251,6 +256,26 @@ class simpleDownloadManager {
251
  wp_nonce_field('sdm_upload_box_nonce', 'sdm_upload_box_nonce_check');
252
  }
253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  public function display_sdm_thumbnail_meta_box($post) { // Thumbnail upload metabox
255
  $old_thumbnail = get_post_meta($post->ID, 'sdm_upload_thumbnail', true);
256
  $old_value = isset($old_thumbnail) ? $old_thumbnail : '';
@@ -378,6 +403,18 @@ class simpleDownloadManager {
378
  }
379
  }
380
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  public function sdm_save_thumbnail_meta_data($post_id) { // Save Thumbnail Upload metabox
382
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
383
  return;
@@ -448,6 +485,7 @@ class simpleDownloadManager {
448
 
449
  //Add all the individual settings fields that goes under the sections
450
  add_settings_field('general_hide_donwload_count', __('Hide Download Count', 'simple-download-monitor'), array($this, 'hide_download_count_cb'), 'general_options_section', 'general_options');
 
451
 
452
  add_settings_field('admin_tinymce_button', __('Remove Tinymce Button', 'simple-download-monitor'), array($this, 'admin_tinymce_button_cb'), 'admin_options_section', 'admin_options');
453
  add_settings_field('admin_log_unique', __('Log Unique IP', 'simple-download-monitor'), array($this, 'admin_log_unique'), 'admin_options_section', 'admin_options');
@@ -473,26 +511,33 @@ class simpleDownloadManager {
473
 
474
  public function hide_download_count_cb() {
475
  $main_opts = get_option('sdm_downloads_options');
476
- echo '<input name="sdm_downloads_options[general_hide_donwload_count]" id="general_hide_donwload_count" type="checkbox" ' . checked(1, isset($main_opts['general_hide_donwload_count']), false) . ' /> ';
477
- _e('Hide the download count that is shown in some of the fancy templates.', 'simple-download-monitor');
 
 
 
 
 
 
 
478
  }
479
 
480
  public function admin_tinymce_button_cb() {
481
  $main_opts = get_option('sdm_downloads_options');
482
  echo '<input name="sdm_downloads_options[admin_tinymce_button]" id="admin_tinymce_button" type="checkbox" class="sdm_opts_ajax_checkboxes" ' . checked(1, isset($main_opts['admin_tinymce_button']), false) . ' /> ';
483
- _e('Removes the SDM Downloads button from the WP content editor.', 'simple-download-monitor');
484
  }
485
 
486
  public function admin_log_unique() {
487
  $main_opts = get_option('sdm_downloads_options');
488
  echo '<input name="sdm_downloads_options[admin_log_unique]" id="admin_log_unique" type="checkbox" class="sdm_opts_ajax_checkboxes" ' . checked(1, isset($main_opts['admin_log_unique']), false) . ' /> ';
489
- _e('Only logs downloads from unique IP addresses.', 'simple-download-monitor');
490
  }
491
 
492
  public function admin_no_logs_cb() {
493
  $main_opts = get_option('sdm_downloads_options');
494
  echo '<input name="sdm_downloads_options[admin_no_logs]" id="admin_no_logs" type="checkbox" class="sdm_opts_ajax_checkboxes" ' . checked(1, isset($main_opts['admin_no_logs']), false) . ' /> ';
495
- _e('Disables all download logs. (This global option overrides the individual download item option.)', 'simple-download-monitor');
496
  }
497
 
498
  public function download_button_color_cb() {
@@ -515,109 +560,6 @@ class simpleDownloadManager {
515
  //Initialize the simpleDownloadManager class
516
  $simpleDownloadManager = new simpleDownloadManager();
517
 
518
- //Handles the download request
519
- function handle_sdm_download_via_direct_post() {
520
- if (isset($_REQUEST['smd_process_download']) && $_REQUEST['smd_process_download'] == '1') {
521
- global $wpdb;
522
- $download_id = strip_tags($_REQUEST['download_id']);
523
- $download_title = get_the_title($download_id);
524
- $download_link = get_post_meta($download_id, 'sdm_upload', true);
525
-
526
- //Do some validation checks
527
- if (empty($download_id)) {
528
- wp_die(__('Error! Incorrect download item id.', 'simple-download-monitor'));
529
- }
530
- if (empty($download_link)) {
531
- wp_die(__('Error! This download item (' . $download_id . ') does not have any download link. Edit this item and specify a downloadable file URL for it.', 'simple-download-monitor'));
532
- }
533
-
534
- //Check download password (if applicable for this download)
535
- $post_object = get_post($download_id);// Get post object
536
- $post_pass = $post_object->post_password;// Get post password
537
- if(!empty($post_pass)){//This download item has a password. So validate the password.
538
- $pass_val = $_REQUEST['pass_text'];
539
- if(empty($pass_val)){//No password was submitted with the downoad request.
540
- wp_die(__('Error! This download requires a password.', 'simple-download-monitor'));
541
- }
542
- if ($post_pass != $pass_val) {
543
- //Incorrect password submitted.
544
- wp_die(__('Error! Incorrect password. This download requires a valid password.', 'simple-download-monitor'));
545
- } else {
546
- //Password is valid. Go ahead with the download
547
- }
548
- }
549
- //End of password check
550
-
551
- $ipaddress = $_SERVER["REMOTE_ADDR"];
552
- $date_time = current_time('mysql');
553
- $visitor_country = sdm_ip_info('Visitor', 'Country');
554
-
555
- if (is_user_logged_in()) { // Get user name (if logged in)
556
- global $current_user;
557
- get_currentuserinfo();
558
- $visitor_name = $current_user->user_login;
559
- } else {
560
- $visitor_name = __('Not Logged In', 'simple-download-monitor');
561
- }
562
-
563
- // Get option for global disabling of download logging
564
- $main_option = get_option('sdm_downloads_options');
565
- $no_logs = isset($main_option['admin_no_logs']);
566
-
567
- // Get optoin for logging only unique IPs
568
- $unique_ips = isset($main_option['admin_log_unique']);
569
-
570
- // Get post meta for individual disabling of download logging
571
- $get_meta = get_post_meta($download_id, 'sdm_item_no_log', true);
572
- $item_logging_checked = isset($get_meta) && $get_meta === 'on' ? 'on' : 'off';
573
-
574
- $dl_logging_needed = true;
575
-
576
- // Check if download logs have been disabled (globally or per download item)
577
- if ($no_logs === true || $item_logging_checked === 'on') {
578
- $dl_logging_needed = false;
579
- }
580
-
581
- // Check if we are only logging unique ips
582
- if ($unique_ips === true) {
583
- $check_ip = $wpdb->get_results('SELECT * FROM ' . $wpdb->prefix . 'sdm_downloads WHERE post_id="' . $download_id . '" AND visitor_ip = "' . $ipaddress . '"');
584
-
585
- //This IP is already logged for this download item. No need to log it again.
586
- if ($check_ip) {
587
- $dl_logging_needed = false;
588
- }
589
- }
590
-
591
- if ($dl_logging_needed) {
592
- // We need to log this download.
593
- $table = $wpdb->prefix . 'sdm_downloads';
594
- $data = array(
595
- 'post_id' => $download_id,
596
- 'post_title' => $download_title,
597
- 'file_url' => $download_link,
598
- 'visitor_ip' => $ipaddress,
599
- 'date_time' => $date_time,
600
- 'visitor_country' => $visitor_country,
601
- 'visitor_name' => $visitor_name
602
- );
603
-
604
- $data = array_filter($data); //Remove any null values.
605
- $insert_table = $wpdb->insert($table, $data);
606
-
607
- if ($insert_table) {
608
- //Download request was logged successfully
609
- } else {
610
- //Failed to log the download request
611
- wp_die(__('Error! Failed to log the download request in the database table', 'simple-download-monitor'));
612
- }
613
- }
614
-
615
- //Downoad the item
616
- sdm_redirect_to_url($download_link);
617
- exit;
618
- }
619
- }
620
-
621
  // Tinymce Button Populate Post ID's
622
  add_action('wp_ajax_nopriv_sdm_tiny_get_post_ids', 'sdm_tiny_get_post_ids_ajax_call');
623
  add_action('wp_ajax_sdm_tiny_get_post_ids', 'sdm_tiny_get_post_ids_ajax_call');
@@ -687,9 +629,10 @@ function sdm_pop_cats_ajax_call() {
687
  'order' => 'ASC')
688
  );
689
 
 
 
690
  // Loop results
691
  foreach ($posts as $post) {
692
-
693
  // Create array of variables to pass to js
694
  $final_array[] = array('id' => $post->ID, 'permalink' => get_permalink($post->ID), 'title' => $post->post_title);
695
  }
3
  * Plugin Name: Simple Download Monitor
4
  * Plugin URI: https://www.tipsandtricks-hq.com/simple-wordpress-download-monitor-plugin
5
  * Description: Easily manage downloadable files and monitor downloads of your digital files from your WordPress site.
6
+ * Version: 3.3.4
7
  * Author: Tips and Tricks HQ, Ruhul Amin, Josh Lobe
8
  * Author URI: https://www.tipsandtricks-hq.com/development-center
9
  * License: GPL2
12
  exit;
13
  }
14
 
15
+ define('WP_SIMPLE_DL_MONITOR_VERSION', '3.3.4');
16
  define('WP_SIMPLE_DL_MONITOR_DIR_NAME', dirname(plugin_basename(__FILE__)));
17
  define('WP_SIMPLE_DL_MONITOR_URL', plugins_url('', __FILE__));
18
  define('WP_SIMPLE_DL_MONITOR_PATH', plugin_dir_path(__FILE__));
24
  //File includes
25
  include_once('includes/sdm-utility-functions.php');
26
  include_once('includes/sdm-utility-functions-admin-side.php');
27
+ include_once('includes/sdm-download-request-handler.php');
28
  include_once('includes/sdm-logs-list-table.php');
29
  include_once('includes/sdm-latest-downloads.php');
30
  include_once('sdm-post-type-and-taxonomy.php');
81
  * * Handle Generic Init tasks
82
  */
83
  add_action('init', 'sdm_init_time_tasks');
 
84
  function sdm_init_time_tasks() {
85
  //Handle download request if any
86
  handle_sdm_download_via_direct_post();
87
  }
88
 
89
+ /*
90
+ * DB upgrade check
91
+ */
92
  function sdm_db_update_check() {
93
  if (is_admin()) {//Check if DB needs to be upgraded
94
  global $sdm_db_version;
123
  add_action('init', 'sdm_register_post_type'); // Create 'sdm_downloads' custom post type
124
  add_action('init', 'sdm_create_taxonomies'); // Register 'tags' and 'categories' taxonomies
125
  add_action('init', 'sdm_register_shortcodes'); //Register the shortcodes
126
+ add_action('wp_enqueue_scripts', array($this, 'sdm_frontend_scripts')); // Register frontend scripts
127
 
128
  if (is_admin()) {
129
+ add_action('admin_menu', array($this, 'sdm_create_menu_pages')); // Create admin pages
130
+ add_action('add_meta_boxes', array($this, 'sdm_create_upload_metabox')); // Create metaboxes
131
 
132
+ add_action('save_post', array($this, 'sdm_save_description_meta_data')); // Save 'description' metabox
133
+ add_action('save_post', array($this, 'sdm_save_upload_meta_data')); // Save 'upload file' metabox
134
+ add_action('save_post', array($this, 'sdm_save_dispatch_meta_data')); // Save 'dispatch' metabox
135
+ add_action('save_post', array($this, 'sdm_save_thumbnail_meta_data')); // Save 'thumbnail' metabox
136
+ add_action('save_post', array($this, 'sdm_save_statistics_meta_data')); // Save 'statistics' metabox
137
+ add_action('save_post', array($this, 'sdm_save_other_details_meta_data')); // Save 'other details' metabox
138
 
139
+ add_action('admin_enqueue_scripts', array($this, 'sdm_admin_scripts')); // Register admin scripts
140
+ add_action('admin_print_styles', array($this, 'sdm_admin_styles')); // Register admin styles
141
 
142
+ add_action('admin_init', array($this, 'sdm_register_options')); // Register admin options
143
+ //add_filter('post_row_actions', array($this, 'sdm_remove_view_link_cpt'), 10, 2); // Remove 'View' link in all downloads list view
144
  }
145
  }
146
 
210
  public function sdm_create_upload_metabox() {
211
 
212
  //***** Create metaboxes for the custom post type
213
+ add_meta_box('sdm_description_meta_box', __('Description', 'simple-download-monitor'), array($this, 'display_sdm_description_meta_box'), 'sdm_downloads', 'normal', 'default');
214
+ add_meta_box('sdm_upload_meta_box', __('Upload File', 'simple-download-monitor'), array($this, 'display_sdm_upload_meta_box'), 'sdm_downloads', 'normal', 'default');
215
+ add_meta_box('sdm_dispatch_meta_box', __('PHP Dispatch or Redirect', 'simple-download-monitor'), array($this, 'display_sdm_dispatch_meta_box'), 'sdm_downloads', 'normal', 'default');
216
+ add_meta_box('sdm_thumbnail_meta_box', __('File Thumbnail (Optional)', 'simple-download-monitor'), array($this, 'display_sdm_thumbnail_meta_box'), 'sdm_downloads', 'normal', 'default');
217
+ add_meta_box('sdm_stats_meta_box', __('Statistics', 'simple-download-monitor'), array($this, 'display_sdm_stats_meta_box'), 'sdm_downloads', 'normal', 'default');
218
+ add_meta_box('sdm_other_details_meta_box', __('Other Details (Optional)', 'simple-download-monitor'), array($this, 'display_sdm_other_details_meta_box'), 'sdm_downloads', 'normal', 'default');
219
+ add_meta_box('sdm_shortcode_meta_box', __('Shortcodes', 'simple-download-monitor'), array($this, 'display_sdm_shortcode_meta_box'), 'sdm_downloads', 'normal', 'default');
220
 
221
  }
222
 
256
  wp_nonce_field('sdm_upload_box_nonce', 'sdm_upload_box_nonce_check');
257
  }
258
 
259
+ public function display_sdm_dispatch_meta_box($post) {
260
+ $dispatch = get_post_meta($post->ID, 'sdm_item_dispatch', true);
261
+
262
+ if ( $dispatch === '' ) {
263
+ // No value yet (either new item or saved with older version of plugin)
264
+ $screen = get_current_screen();
265
+
266
+ if ( $screen->action === 'add' ) {
267
+ // New item: set default value as per plugin settings.
268
+ $main_opts = get_option('sdm_downloads_options');
269
+ $dispatch = isset($main_opts['general_default_dispatch_value']) && $main_opts['general_default_dispatch_value'];
270
+ }
271
+ }
272
+
273
+ echo '<input id="sdm_item_dispatch" type="checkbox" name="sdm_item_dispatch" value="yes"' . checked(true, $dispatch, false) . ' />';
274
+ echo '<label for="sdm_item_dispatch">' . __('Dispatch the file via PHP directly instead of redirecting to it. PHP Dispatching keeps the download URL hidden. Dispatching works only for local files (files that you uploaded to this site via this plugin or media library).', 'simple-download-monitor') . '</label>';
275
+
276
+ wp_nonce_field('sdm_dispatch_box_nonce', 'sdm_dispatch_box_nonce_check');
277
+ }
278
+
279
  public function display_sdm_thumbnail_meta_box($post) { // Thumbnail upload metabox
280
  $old_thumbnail = get_post_meta($post->ID, 'sdm_upload_thumbnail', true);
281
  $old_value = isset($old_thumbnail) ? $old_thumbnail : '';
403
  }
404
  }
405
 
406
+ public function sdm_save_dispatch_meta_data($post_id) { // Save "Dispatch or Redirect" metabox
407
+ if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
408
+ return;
409
+ }
410
+ if ( !isset($_POST['sdm_dispatch_box_nonce_check']) || !wp_verify_nonce($_POST['sdm_dispatch_box_nonce_check'], 'sdm_dispatch_box_nonce') ) {
411
+ return;
412
+ }
413
+ // Get POST-ed data as boolean value
414
+ $value = filter_input(INPUT_POST, 'sdm_item_dispatch', FILTER_VALIDATE_BOOLEAN);
415
+ update_post_meta($post_id, 'sdm_item_dispatch', $value);
416
+ }
417
+
418
  public function sdm_save_thumbnail_meta_data($post_id) { // Save Thumbnail Upload metabox
419
  if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
420
  return;
485
 
486
  //Add all the individual settings fields that goes under the sections
487
  add_settings_field('general_hide_donwload_count', __('Hide Download Count', 'simple-download-monitor'), array($this, 'hide_download_count_cb'), 'general_options_section', 'general_options');
488
+ add_settings_field('general_default_dispatch_value', __('PHP Dispatching', 'simple-download-monitor'), array($this, 'general_default_dispatch_value_cb'), 'general_options_section', 'general_options');
489
 
490
  add_settings_field('admin_tinymce_button', __('Remove Tinymce Button', 'simple-download-monitor'), array($this, 'admin_tinymce_button_cb'), 'admin_options_section', 'admin_options');
491
  add_settings_field('admin_log_unique', __('Log Unique IP', 'simple-download-monitor'), array($this, 'admin_log_unique'), 'admin_options_section', 'admin_options');
511
 
512
  public function hide_download_count_cb() {
513
  $main_opts = get_option('sdm_downloads_options');
514
+ echo '<input name="sdm_downloads_options[general_hide_donwload_count]" id="general_hide_download_count" type="checkbox" ' . checked(1, isset($main_opts['general_hide_donwload_count']), false) . ' /> ';
515
+ echo '<label for="general_hide_download_count">' . __('Hide the download count that is shown in some of the fancy templates.', 'simple-download-monitor') . '</label>';
516
+ }
517
+
518
+ public function general_default_dispatch_value_cb() {
519
+ $main_opts = get_option('sdm_downloads_options');
520
+ $value = isset($main_opts['general_default_dispatch_value']) && $main_opts['general_default_dispatch_value'];
521
+ echo '<input name="sdm_downloads_options[general_default_dispatch_value]" id="general_default_dispatch_value" type="checkbox" value="1"' . checked(true, $value, false) . ' />';
522
+ echo '<label for="general_default_dispatch_value">' . __('When you create a new download item, The PHP Dispatching option should be enabled by default. PHP Dispatching keeps the URL of the downloadable files hidden.', 'simple-download-monitor') . '</label>';
523
  }
524
 
525
  public function admin_tinymce_button_cb() {
526
  $main_opts = get_option('sdm_downloads_options');
527
  echo '<input name="sdm_downloads_options[admin_tinymce_button]" id="admin_tinymce_button" type="checkbox" class="sdm_opts_ajax_checkboxes" ' . checked(1, isset($main_opts['admin_tinymce_button']), false) . ' /> ';
528
+ echo '<label for="admin_tinymce_button">' . __('Removes the SDM Downloads button from the WP content editor.', 'simple-download-monitor') . '</label>';
529
  }
530
 
531
  public function admin_log_unique() {
532
  $main_opts = get_option('sdm_downloads_options');
533
  echo '<input name="sdm_downloads_options[admin_log_unique]" id="admin_log_unique" type="checkbox" class="sdm_opts_ajax_checkboxes" ' . checked(1, isset($main_opts['admin_log_unique']), false) . ' /> ';
534
+ echo '<label for="admin_log_unique">' . __('Only logs downloads from unique IP addresses.', 'simple-download-monitor') . '</label>';
535
  }
536
 
537
  public function admin_no_logs_cb() {
538
  $main_opts = get_option('sdm_downloads_options');
539
  echo '<input name="sdm_downloads_options[admin_no_logs]" id="admin_no_logs" type="checkbox" class="sdm_opts_ajax_checkboxes" ' . checked(1, isset($main_opts['admin_no_logs']), false) . ' /> ';
540
+ echo '<label for="admin_no_logs">' . __('Disables all download logs. (This global option overrides the individual download item option.)', 'simple-download-monitor') . '</label>';
541
  }
542
 
543
  public function download_button_color_cb() {
560
  //Initialize the simpleDownloadManager class
561
  $simpleDownloadManager = new simpleDownloadManager();
562
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
  // Tinymce Button Populate Post ID's
564
  add_action('wp_ajax_nopriv_sdm_tiny_get_post_ids', 'sdm_tiny_get_post_ids_ajax_call');
565
  add_action('wp_ajax_sdm_tiny_get_post_ids', 'sdm_tiny_get_post_ids_ajax_call');
629
  'order' => 'ASC')
630
  );
631
 
632
+ $final_array = array();
633
+
634
  // Loop results
635
  foreach ($posts as $post) {
 
636
  // Create array of variables to pass to js
637
  $final_array[] = array('id' => $post->ID, 'permalink' => get_permalink($post->ID), 'title' => $post->post_title);
638
  }
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Simple Download Monitor ===
2
- Contributors: Tips and Tricks HQ, Ruhul Amin, josh401, mbrsolution
3
  Donate link: https://www.tipsandtricks-hq.com
4
  Tags: download, downloads, count, counter, tracker, tracking, hits, logging, monitor, manager, files, media, digital, download monitor, download manager, downloadmanager, file manager, protect downloads, password, download category, file tree, ajax, download template, grid, documents, ip address
5
- Requires at least: 3.0
6
  Tested up to: 4.6
7
- Stable tag: 3.3.2
8
  License: GPLv2 or later
9
 
10
  Easily manage downloadable files and monitor downloads of your digital files from your WordPress site.
@@ -41,6 +41,7 @@ https://www.youtube.com/watch?v=L-mXbs7kp0s
41
  * Track IP addresses of the users who downloaded your files.
42
  * Track date and time of each file downloads.
43
  * Track the usernames of the users downloading the files.
 
44
  * Option to upload a thumbnail image for each of your downloadable files.
45
  * Option to use a nice looking template to show your download now buttons.
46
  * Ability to search and sort your downloadable files in the admin dashboard.
@@ -50,7 +51,7 @@ https://www.youtube.com/watch?v=L-mXbs7kp0s
50
  * Tinymce button in the WordPress post/page editor so you can easily add the shortcode.
51
  * You can customize the "Download Now" button text of an item to anything you want.
52
  * Ability to add the download now buttons to your sidebar widget.
53
- * Create password protected download now buttons. Users will only be able to download the file if they enter the correct password. [View the tutorial](http://www.tipsandtricks-hq.com/create-a-password-protected-download-file-6838)
54
  * Shortcode to show the download counter of a file. Use it to show off your file download count.
55
  * Shortcode to show all the downloads from a particular category.
56
  * Shortcode to embed a file tree browser for your downloadable files. The file browser is ajax based and it shows the files structured by categories.
@@ -167,6 +168,17 @@ For screenshots please visit the [download monitor plugin page](https://www.tips
167
 
168
  == Changelog ==
169
 
 
 
 
 
 
 
 
 
 
 
 
170
  = 3.3.2 =
171
  - Added an option to specify the file size info when editing the item. Size info can be shown in the fancy display template using a shortcode parameter (show_size).
172
  - Added an option to specify the version number info when editing the item. Version info can be shown in the fancy display template using a shortcode parameter (show_version).
1
  === Simple Download Monitor ===
2
+ Contributors: Tips and Tricks HQ, Ruhul Amin, josh401, mbrsolution, chesio
3
  Donate link: https://www.tipsandtricks-hq.com
4
  Tags: download, downloads, count, counter, tracker, tracking, hits, logging, monitor, manager, files, media, digital, download monitor, download manager, downloadmanager, file manager, protect downloads, password, download category, file tree, ajax, download template, grid, documents, ip address
5
+ Requires at least: 3.3.0
6
  Tested up to: 4.6
7
+ Stable tag: 3.3.4
8
  License: GPLv2 or later
9
 
10
  Easily manage downloadable files and monitor downloads of your digital files from your WordPress site.
41
  * Track IP addresses of the users who downloaded your files.
42
  * Track date and time of each file downloads.
43
  * Track the usernames of the users downloading the files.
44
+ * Option to setup secure downloads for your files (the URL of the downloadable file will be hidden).
45
  * Option to upload a thumbnail image for each of your downloadable files.
46
  * Option to use a nice looking template to show your download now buttons.
47
  * Ability to search and sort your downloadable files in the admin dashboard.
51
  * Tinymce button in the WordPress post/page editor so you can easily add the shortcode.
52
  * You can customize the "Download Now" button text of an item to anything you want.
53
  * Ability to add the download now buttons to your sidebar widget.
54
+ * Create password protected download now buttons. Users will only be able to download the file if they enter the correct password. [View the tutorial](https://www.tipsandtricks-hq.com/create-a-password-protected-download-file-6838)
55
  * Shortcode to show the download counter of a file. Use it to show off your file download count.
56
  * Shortcode to show all the downloads from a particular category.
57
  * Shortcode to embed a file tree browser for your downloadable files. The file browser is ajax based and it shows the files structured by categories.
168
 
169
  == Changelog ==
170
 
171
+ = 3.3.4 =
172
+ - Replace deprecated get_currentuserinfo() with wp_get_current_user()
173
+ - Improve remote IP and location detection
174
+ - Added a new shortcode to show a simple list of the download categories
175
+ - Fix: avoid undefined variable notices in sdm_pop_cats_ajax_call()
176
+
177
+ = 3.3.3 =
178
+ - New feature - local download items can now be dispatched via PHP. This way, the actual URL of the downloaded file is not exposed (offers secure download).
179
+ - Minimum required WP version raised to WordPress v3.3
180
+ - WordPress 4.6 compatibility.
181
+
182
  = 3.3.2 =
183
  - Added an option to specify the file size info when editing the item. Size info can be shown in the fancy display template using a shortcode parameter (show_size).
184
  - Added an option to specify the version number info when editing the item. Version info can be shown in the fancy display template using a shortcode parameter (show_version).
sdm-shortcodes.php CHANGED
@@ -19,6 +19,7 @@ function sdm_register_shortcodes() {
19
  add_shortcode('sdm_show_dl_from_category', 'sdm_handle_category_shortcode'); //For category shortcode
20
  add_shortcode('sdm_download_categories', 'sdm_download_categories_shortcode'); // Ajax file tree browser
21
 
 
22
  }
23
 
24
  // Create Download Shortcode
@@ -301,4 +302,70 @@ function sdm_download_categories_shortcode() {
301
  }
302
 
303
  return '<div class="sdm_object_tree">' . custom_taxonomy_walker('sdm_categories') . '</div>';
304
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  add_shortcode('sdm_show_dl_from_category', 'sdm_handle_category_shortcode'); //For category shortcode
20
  add_shortcode('sdm_download_categories', 'sdm_download_categories_shortcode'); // Ajax file tree browser
21
 
22
+ add_shortcode('sdm_download_categories_list', 'sdm_download_categories_list_shortcode');
23
  }
24
 
25
  // Create Download Shortcode
302
  }
303
 
304
  return '<div class="sdm_object_tree">' . custom_taxonomy_walker('sdm_categories') . '</div>';
305
+ }
306
+
307
+
308
+ /**
309
+ * Return HTML list with SDM categories rendered according to $atts.
310
+ * @param array $atts
311
+ * @param int $parent
312
+ * @return string
313
+ */
314
+ function sdm_download_categories_list_walker($atts, $parent = 0) {
315
+
316
+ $count = (bool) $atts['count'];
317
+ $hierarchical = (bool) $atts['hierarchical'];
318
+ $show_empty = (bool) $atts['empty'];
319
+ $list_tag = $atts['numbered'] ? 'ol' : 'ul';
320
+
321
+ // Get terms (check if has parent)
322
+ $terms = get_terms(array(
323
+ 'taxonomy' => 'sdm_categories',
324
+ 'parent' => $parent,
325
+ 'hide_empty' => !$show_empty
326
+ ));
327
+
328
+ // Return empty string, if no terms found.
329
+ if ( empty($terms) ) { return ''; }
330
+
331
+ // Produce list of download categories under $parent.
332
+ $out .= '<' . $list_tag . '>';
333
+
334
+ foreach ( $terms as $term ) {
335
+ $out .= '<li>'
336
+ . '<a href="' . get_term_link($term) . '">' . $term->name . '</a>' // link
337
+ . ( $count ? (' <span>(' . $term->count . ')</span>') : '') // count
338
+ . ( $hierarchical ? sdm_download_categories_list_walker($atts, $term->term_id) : '' ) // subcategories
339
+ . '</li>'
340
+ ;
341
+ }
342
+
343
+ $out .= '</' . $list_tag . '>';
344
+
345
+ return $out;
346
+ }
347
+
348
+
349
+ /**
350
+ * Return output of `sdm_download_categories_list` shortcode.
351
+ * @param array $attributes
352
+ * @return string
353
+ */
354
+ function sdm_download_categories_list_shortcode($attributes) {
355
+
356
+ $atts = shortcode_atts(
357
+ array(
358
+ 'class' => 'sdm-download-categories', // wrapper class
359
+ 'empty' => '0', // show empty categories
360
+ 'numbered' => '0', // use <ol> instead of <ul> to wrap the list
361
+ 'count' => '0', // display count of items in every category
362
+ 'hierarchical' => '1', // display subcategories as well
363
+ ), $attributes
364
+ );
365
+
366
+ return
367
+ '<div class="' . esc_attr($atts['class']) . '">'
368
+ . sdm_download_categories_list_walker($atts)
369
+ . '</div>'
370
+ ;
371
+ }