views
2 days ago
FileList.php
4 years ago
Hooks.php
3 years ago
Package.php
1 year ago
PackageController.php
6 months ago
PackageLocks.php
5 months ago
PackageTemplate.php
4 years ago
RestAPI.php
3 years ago
Shortcodes.php
2 days ago
Shortcodes.php
498 lines
| 1 | <?php |
| 2 | |
| 3 | |
| 4 | namespace WPDM\Package; |
| 5 | |
| 6 | |
| 7 | use WPDM\__\__; |
| 8 | use WPDM\__\Messages; |
| 9 | use WPDM\__\Template; |
| 10 | use WPDM\__\Crypt; |
| 11 | use WPDM\__\Query; |
| 12 | use WPDM\__\UI; |
| 13 | |
| 14 | class Shortcodes |
| 15 | { |
| 16 | function __construct() |
| 17 | { |
| 18 | // Single package shortcode |
| 19 | add_shortcode("wpdm_package", [$this, 'singlePackage']); |
| 20 | |
| 21 | // Generate direct download link |
| 22 | add_shortcode('wpdm_direct_link', [$this, 'directLink']); |
| 23 | |
| 24 | // Show all packages |
| 25 | add_shortcode('wpdm_packages', [$this, 'packages']); |
| 26 | |
| 27 | //Packages by tag |
| 28 | add_shortcode("wpdm_tag", [$this, 'packagesByTag']); |
| 29 | |
| 30 | // Total Package Count |
| 31 | add_shortcode('wpdm_download_count', [$this, 'totalDownloads']); |
| 32 | |
| 33 | // Total Package Count |
| 34 | add_shortcode('wpdm_package_count', [$this, 'totalPackages']); |
| 35 | |
| 36 | // Show all packages in a responsive table |
| 37 | add_shortcode('wpdm_all_packages', [$this, 'allPackages']); |
| 38 | add_shortcode('wpdm-all-packages', [$this, 'allPackages']); |
| 39 | |
| 40 | //Search downloads |
| 41 | add_shortcode('wpdm_search_result', [$this, 'searchResult']); |
| 42 | |
| 43 | // Changelog display |
| 44 | add_shortcode("wpdm_changelog", [$this, 'changelog']); |
| 45 | |
| 46 | |
| 47 | } |
| 48 | |
| 49 | /** |
| 50 | * Callback function for [wpdm_package..] |
| 51 | * @param array $params |
| 52 | * @return string |
| 53 | */ |
| 54 | function singlePackage($params = []) |
| 55 | { |
| 56 | $id = wpdm_valueof($params, 'id', [ 'validate' => 'int' ]); |
| 57 | |
| 58 | if(!$id && is_singular('wpdmpro')) $id = get_the_ID(); |
| 59 | |
| 60 | //Return if id is invalid |
| 61 | if (!$id || get_post_type($id) !== 'wpdmpro') return ''; |
| 62 | |
| 63 | if (get_post_status($id) !== 'publish' && !is_user_logged_in()) return Messages::permission_denied($id, __('Private File - Access Forbidden', 'download-manager')); |
| 64 | |
| 65 | //Link template |
| 66 | $template = isset($params['template']) ? $params['template'] : get_post_meta($id, '__wpdm_template', true); |
| 67 | if ($template == '') $template = 'link-template-default.php'; |
| 68 | $template = wp_basename($template); |
| 69 | $pack = new Package($id); |
| 70 | $html = "<div class='w3eden'>" . $pack->fetchTemplate($template, $id, 'link') . "</div>"; |
| 71 | |
| 72 | return $html; |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * @usage Generate direct link to download |
| 77 | * @param $params |
| 78 | * @param string $content |
| 79 | * @return string |
| 80 | */ |
| 81 | function directLink($params, $content = "") |
| 82 | { |
| 83 | extract($params); |
| 84 | |
| 85 | global $wpdb; |
| 86 | $ID = (int)$params['id']; |
| 87 | |
| 88 | if (WPDM()->package->isLocked($ID)) |
| 89 | $linkURL = get_permalink($ID); |
| 90 | else |
| 91 | $linkURL = home_url("/?wpdmdl=" . $ID); |
| 92 | |
| 93 | $target = isset($params['target']) ? "target='" . wpdm_sanitize_var($params['target'], 'esc_attr') . "'" : ""; |
| 94 | $class = isset($params['class']) ? "class='" . wpdm_sanitize_var($params['class'], 'esc_attr') . "'" : ""; |
| 95 | $style = isset($params['style']) ? "style='" . wpdm_sanitize_var($params['style'], 'esc_attr') . "'" : ""; |
| 96 | $rel = isset($params['rel']) ? "rel='" . wpdm_sanitize_var($params['rel'], 'esc_attr') . "'" : ""; |
| 97 | $eid = isset($params['eid']) ? "id='" . wpdm_sanitize_var($params['eid'], 'esc_attr') . "'" : ""; |
| 98 | $linkLabel = isset($params['label']) && !empty($params['label']) ? $params['label'] : get_post_meta($ID, '__wpdm_link_label', true); |
| 99 | $linkLabel = empty($linkLabel) ? get_the_title($ID) : $linkLabel; |
| 100 | $linkLabel = wpdm_sanitize_var($linkLabel, 'kses'); |
| 101 | return "<a {$target} {$class} {$eid} {$style} {$rel} href='$linkURL'>".esc_attr($linkLabel)."</a>"; |
| 102 | |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * @param array $params |
| 107 | * @return string |
| 108 | */ |
| 109 | /** |
| 110 | * @param array $params |
| 111 | * @return string |
| 112 | */ |
| 113 | function packages($params = array('items_per_page' => 10, 'title' => '', 'desc' => '', 'orderby' => 'date', 'order' => 'DESC', 'paging' => false, 'page_numbers' => true, 'toolbar' => 1, 'template' => '', 'cols' => 3, 'colspad' => 2, 'colsphone' => 1, 'tags' => '', 'categories' => '', 'year' => '', 'month' => '', 's' => '', 'css_class' => 'wpdm_packages', 'scid' => '', 'async' => 1, 'tax' => '', 'terms' => '', 'not_found' => 'No downloads available!')) |
| 114 | { |
| 115 | global $current_user, $post; |
| 116 | |
| 117 | static $wpdm_packages = 0; |
| 118 | |
| 119 | $params = __::a($params, ['items_per_page' => 10, 'title' => '', 'desc' => '', 'orderby' => 'date', 'order' => 'DESC', 'paging' => false, 'page_numbers' => true, 'toolbar' => 1, 'template' => '', 'cols' => 3, 'colspad' => 2, 'colsphone' => 1, 'tags' => '', 'categories' => '', 'year' => '', 'month' => '', 's' => '', 'css_class' => 'wpdm_packages', 'scid' => '', 'async' => 1, 'tax' => '', 'terms' => '', 'not_found' => 'No downloads available!']); |
| 120 | |
| 121 | // When login=1, show login form for guests/visitors |
| 122 | if (isset($params['login']) && $params['login'] == 1 && !is_user_logged_in()) |
| 123 | return WPDM()->user->login->form($params); |
| 124 | |
| 125 | // To generate unique sections ID when someone uses multiple shortcode on a page |
| 126 | $wpdm_packages++; |
| 127 | |
| 128 | // $scparams = Initial unprocessed shortcode parameters |
| 129 | $scparams = $params; |
| 130 | |
| 131 | |
| 132 | |
| 133 | $async = __::valueof($params, 'async', ['default' => 0, 'validate' => 'int']); |
| 134 | $items_per_page = __::valueof($params, 'items_per_page', 10); |
| 135 | if($items_per_page < 1) $items_per_page = 10; |
| 136 | $scid = __::valueof($params, 'scid', ['default' => 'wpdm_package_'.$wpdm_packages, 'validate' => 'esc_attr']); |
| 137 | $cwd_class = "col-lg-" . (int)(12 / __::valueof($params, 'cols', ['default' => 3, 'validate' => 'int'])); |
| 138 | $cwdsm_class = "col-md-" . (int)(12 / __::valueof($params, 'colspad', ['default' => 2, 'validate' => 'int'])); |
| 139 | $cwdxs_class = "col-" . (int)(12 / __::valueof($params, 'colsphone', ['default' => 1, 'validate' => 'int'])); |
| 140 | |
| 141 | $title = __::valueof($params, 'title', ['validate' => 'esc_attr']); |
| 142 | $desc = __::valueof($params, 'desc', ['validate' => 'txt']); |
| 143 | $toolbar = __::valueof($params, 'toolbar', ['default' => 1, 'validate' => 'int']); |
| 144 | $paging = __::valueof($params, 'paging', ['default' => 1, 'validate' => 'int']); |
| 145 | |
| 146 | $order_field = __::valueof($params, 'orderby', 'date'); |
| 147 | $order_field = isset($_REQUEST['orderby'])? wpdm_query_var('orderby') : $order_field; |
| 148 | $order = __::valueof($params, 'order', 'desc'); |
| 149 | $order = isset($_REQUEST['order'])? wpdm_query_var('order') : $order; |
| 150 | |
| 151 | $currentPage = __::query_var('cp', 'int'); |
| 152 | if (!$currentPage) $currentPage = 1; |
| 153 | |
| 154 | $query = new Query(); |
| 155 | $query->items_per_page(wpdm_valueof($params, 'items_per_page', 10)); |
| 156 | $query->paged($currentPage); |
| 157 | $query->sort($order_field, $order); |
| 158 | |
| 159 | foreach ($scparams as $key => $value) { |
| 160 | if (method_exists($query, $key) && !in_array($key, ['categories', 'tags'])) { |
| 161 | $query->$key($value); |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | /** |
| 166 | * Process "categories" parameter |
| 167 | * Usually values are category slug(s), users may use id(s) too |
| 168 | * If users uses slugs, convert slugs into ids |
| 169 | **/ |
| 170 | if(wpdm_valueof($scparams, 'categories') !== '') { |
| 171 | $categories = wpdm_valueof($scparams, 'categories'); |
| 172 | $categories = explode(",", $categories); |
| 173 | /** |
| 174 | * Convert slugs to ID |
| 175 | */ |
| 176 | foreach ($categories as &$cat) { |
| 177 | if (!is_numeric($cat) && $cat !== '') { |
| 178 | $catObj = get_term_by('slug', $cat, 'wpdmcategory'); |
| 179 | $cat = $catObj->term_id; |
| 180 | } |
| 181 | } |
| 182 | $operator = wpdm_valueof($scparams, 'operator', ['default' => 'IN']); |
| 183 | $include_children = wpdm_valueof($scparams, 'include_children', ['default' => false]); |
| 184 | $query->categories($categories, 'term_id', $operator, $include_children); |
| 185 | } |
| 186 | |
| 187 | if(wpdm_valueof($scparams, 'tags') !== '') { |
| 188 | $tags = wpdm_valueof($scparams, 'tags'); |
| 189 | $operator = wpdm_valueof($scparams, 'operator', ['default' => 'IN']); |
| 190 | $query->tags($tags, 'slug', $operator); |
| 191 | } |
| 192 | |
| 193 | if (wpdm_query_var('skw', 'txt') != '') { |
| 194 | $query->s(wpdm_query_var('skw', 'txt')); |
| 195 | } |
| 196 | |
| 197 | if(wpdm_valueof($scparams, 'tax') !== '') { |
| 198 | $_terms = explode("|", wpdm_valueof($scparams, 'terms')); |
| 199 | $taxos = explode("|", wpdm_valueof($scparams, 'tax')); |
| 200 | foreach ($taxos as $index => $_taxo) { |
| 201 | $terms = wpdm_valueof($_terms, $index); |
| 202 | $terms = explode(",", $terms); |
| 203 | if(count($terms) > 0) { |
| 204 | |
| 205 | $query->taxonomy($_taxo, $terms); |
| 206 | } |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | $query->taxonomy_relation(wpdm_valueof($scparams, 'relation', ['default' => 'AND'])); |
| 211 | |
| 212 | if (get_option('_wpdm_hide_all', 0) == 1) { |
| 213 | $query->meta("__wpdm_access", '"guest"'); |
| 214 | |
| 215 | if (is_user_logged_in()) { |
| 216 | foreach ($current_user->roles as $role) { |
| 217 | $query->meta("__wpdm_access", $role); |
| 218 | } |
| 219 | $query->meta_relation('OR'); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | // Date filter |
| 224 | if (isset($scparams['year']) || isset($scparams['month']) || isset($scparams['day'])) { |
| 225 | |
| 226 | if (isset($scparams['day'])) { |
| 227 | $day = ($scparams['day'] == 'today') ? date('d') : $scparams['day']; |
| 228 | $query->filter('day', $day); |
| 229 | } |
| 230 | |
| 231 | if (isset($scparams['month'])) { |
| 232 | $month = ($scparams['month'] == 'this') ? date('Ym') : $scparams['month']; |
| 233 | $query->filter('m', $month); |
| 234 | } |
| 235 | |
| 236 | if (isset($scparams['year'])) { |
| 237 | $year = ($scparams['year'] == 'this') ? date('Y') : $scparams['year']; |
| 238 | $query->filter('year', $year); |
| 239 | } |
| 240 | |
| 241 | if (isset($scparams['week'])) { |
| 242 | $week = ($scparams['week'] == 'this') ? date('W') : $scparams['week']; |
| 243 | $query->filter('week', $week); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | $query->post_status('publish'); |
| 248 | $query->process(); |
| 249 | $total = $query->count; |
| 250 | $packages = $query->packages(); |
| 251 | |
| 252 | $pages = ceil($total / $items_per_page); |
| 253 | $page = isset($_GET['cp']) ? (int)$_GET['cp'] : 1; |
| 254 | $start = ($page - 1) * $items_per_page; |
| 255 | |
| 256 | |
| 257 | $html = ''; |
| 258 | $template = wpdm_valueof($scparams, 'template', 'link-template-default.php'); |
| 259 | $template = wp_basename($template); |
| 260 | foreach ($packages as $pack){ |
| 261 | $pack = (array)$pack; |
| 262 | //$repeater = "<div class='{$cwd_class} {$cwdsm_class} {$cwdxs_class}'>" . \WPDM\Package::fetchTemplate(wpdm_valueof($scparams, 'template', 'link-template-default.php'), $pack) . "</div>"; |
| 263 | $repeater = "<div class='{$cwd_class} {$cwdsm_class} {$cwdxs_class}'>" . WPDM()->package->fetchTemplate($template, $pack) . "</div>"; |
| 264 | $html .= $repeater; |
| 265 | |
| 266 | } |
| 267 | |
| 268 | $not_found_msg = wp_kses_post(wpdm_valueof($scparams, 'not_found')) ?: __('No downloads found!', WPDM_TEXT_DOMAIN); |
| 269 | if($total === 0) $html = "<div class='col-md-12'>{$not_found_msg}</div>"; |
| 270 | |
| 271 | $html = "<div class='row'>{$html}</div>"; |
| 272 | |
| 273 | $_scparams = Crypt::encrypt($scparams); |
| 274 | if (!isset($paging) || intval($paging) == 1) { |
| 275 | //sc_params={$_scparams}& |
| 276 | $pag_links = wpdm_paginate_links($total, $items_per_page, $page, 'cp', array( 'format' => "?cp=%#%",'container' => '#content_' . $scid, 'async' => $async, 'next_text' => ' <i style="display: inline-block;width: 8px;height: 8px;border-right: 2px solid;border-top: 2px solid;transform: rotate(45deg);margin-left: -2px;margin-top: -2px;"></i> ', 'prev_text' => ' <i style="display: inline-block;width: 8px;height: 8px;border-right: 2px solid;border-bottom: 2px solid;transform: rotate(135deg);margin-left: 2px;margin-top: -2px;"></i> ')); |
| 277 | $pagination = "<div style='clear:both'></div>" . $pag_links . "<div style='clear:both'></div>"; |
| 278 | } else |
| 279 | $pagination = ""; |
| 280 | |
| 281 | global $post; |
| 282 | |
| 283 | $burl = get_permalink(); |
| 284 | $sap = get_option('permalink_structure') ? '?' : '&'; |
| 285 | $burl = $burl . $sap; |
| 286 | if (isset($_GET['p']) && $_GET['p'] != '') $burl .= 'p=' . wpdm_query_var('p', 'txt') . '&'; |
| 287 | if (isset($_GET['src']) && $_GET['src'] != '') $burl .= 'src=' . wpdm_query_var('src', 'txt') . '&'; |
| 288 | $orderby = isset($_GET['orderby']) ? wpdm_query_var('orderby', 'txt') : 'date'; |
| 289 | $order = ucfirst($order); |
| 290 | |
| 291 | $order_field = " " . __(ucwords(str_replace("_", " ", $order_field)), "wpdmpro"); |
| 292 | $ttitle = __("Title", "download-manager"); |
| 293 | $tdls = __("Downloads", "download-manager"); |
| 294 | $tcdate = __("Publish Date", "download-manager"); |
| 295 | $tudate = __("Update Date", "download-manager"); |
| 296 | $tasc = __("Asc", "download-manager"); |
| 297 | $tdsc = __("Desc", "download-manager"); |
| 298 | $tsrc = __("Search", "download-manager"); |
| 299 | $ord = __("Order", "download-manager"); |
| 300 | $order_by_label = __("Order By", "download-manager"); |
| 301 | |
| 302 | $css_class = isset($scparams['css_class']) ? sanitize_text_field($scparams['css_class']) : ''; |
| 303 | $desc = isset($scparams['desc']) ? sanitize_text_field($scparams['desc']) : ''; |
| 304 | |
| 305 | $toolbar = isset($toolbar) ? $toolbar : 0; |
| 306 | |
| 307 | ob_start(); |
| 308 | include Template::locate("packages-shortcode.php", __DIR__.'/views'); |
| 309 | $content = ob_get_clean(); |
| 310 | return $content; |
| 311 | } |
| 312 | |
| 313 | /** |
| 314 | * @usage Show packages by tag |
| 315 | * @param $params |
| 316 | * @return string |
| 317 | */ |
| 318 | function packagesByTag($params) |
| 319 | { |
| 320 | if(!$params || !isset($params['id'])) return ''; |
| 321 | |
| 322 | $params['tags'] = $params['id']; |
| 323 | unset($params['id']); |
| 324 | return $this->packages($params); |
| 325 | |
| 326 | } |
| 327 | |
| 328 | |
| 329 | /** |
| 330 | * @param array $params |
| 331 | * @return array|null|\WP_Post |
| 332 | * @usage Shortcode callback function for [wpdm_search_result] |
| 333 | */ |
| 334 | function searchResult($params = array()) |
| 335 | { |
| 336 | global $wpdb; |
| 337 | |
| 338 | if (is_array($params)) |
| 339 | @extract($params); |
| 340 | $template = isset($template) && $template != '' ? $template : 'link-template-calltoaction3'; |
| 341 | $async = isset($async) ? $async : 0; |
| 342 | update_post_meta(get_the_ID(), "__wpdm_link_template", $template); |
| 343 | $strm = wpdm_query_var('search', 'esc_attr'); |
| 344 | if ($strm === '') $strm = wpdm_query_var('s', 'esc_attr'); |
| 345 | //$strm = esc_attr($strm); |
| 346 | $html = ''; |
| 347 | $cols = isset($cols) ? $cols : 1; |
| 348 | $items_per_page = isset($items_per_page) ? $items_per_page : $cols * 6; |
| 349 | update_post_meta(get_the_ID(), "__wpdm_items_per_page", $items_per_page); |
| 350 | $colspad = isset($colspad) ? $colspad : 1; |
| 351 | $colsphone = isset($colsphone) ? $colsphone : 1; |
| 352 | if (($strm == '' && isset($init) && $init == 1) || $strm != '') |
| 353 | $html = $this->packages(array('items_per_page' => $items_per_page, 'template' => $template, 's' => $strm, 'paging' => true, 'toolbar' => 0, 'cols' => $cols, 'colsphone' => $colsphone, 'colspad' => $colspad, 'async' => $async)); |
| 354 | $html = "<div class='w3eden'><form id='wpdm-search-form' style='margin-bottom: 20px'><div class='input-group input-group-lg'><div class='input-group-addon input-group-prepend'><span class=\"input-group-text\"><i class='fas fa-search'></i></span></div><input type='text' name='search' value='" . $strm . "' class='form-control input-lg' /></div></form>{$html}</div>"; |
| 355 | return str_replace(array("\r", "\n"), "", $html); |
| 356 | } |
| 357 | |
| 358 | /** |
| 359 | * @usage Short-code function for total download count |
| 360 | * @param array $params |
| 361 | * @return mixed |
| 362 | */ |
| 363 | function totalDownloads($params = array()) |
| 364 | { |
| 365 | global $wpdb; |
| 366 | $download_count = $wpdb->get_var("select sum(meta_value) from {$wpdb->prefix}postmeta where meta_key='__wpdm_download_count'"); |
| 367 | return $download_count; |
| 368 | } |
| 369 | |
| 370 | /** |
| 371 | * @usage Short-code function for total package count |
| 372 | * @param array $params |
| 373 | * @return mixed |
| 374 | */ |
| 375 | function totalPackages($params = array()) |
| 376 | { |
| 377 | if (isset($params['cat'])) { |
| 378 | $term = get_term_by("slug", $params['cat']); |
| 379 | if (is_object($term) && isset($term->count)) return $term->count; |
| 380 | return 0; |
| 381 | } |
| 382 | if (isset($params['author'])) { |
| 383 | $user_post_count = count_user_posts($params['author'], 'wpdmpro'); |
| 384 | return $user_post_count; |
| 385 | } |
| 386 | $count_posts = wp_count_posts('wpdmpro'); |
| 387 | $status = isset($params['status']) ? $params['status'] : 'publish'; |
| 388 | if ($status == 'draft') return $count_posts->draft; |
| 389 | if ($status == 'pending') return $count_posts->pending; |
| 390 | return $count_posts->publish; |
| 391 | } |
| 392 | |
| 393 | /** |
| 394 | * @usage Short-code [wpdm_all_packages] to list all packages in tabular format |
| 395 | * @param array $params |
| 396 | * @return string |
| 397 | */ |
| 398 | function allPackages($params = array()) |
| 399 | { |
| 400 | global $wpdb, $current_user, $wp_query; |
| 401 | |
| 402 | $params = __::a($params, ['items_per_page' => 20]); |
| 403 | |
| 404 | // Defense-in-depth: a contributor-supplied "no data" message must not be |
| 405 | // able to smuggle markup into the shortcode output. sanitize_text_field() |
| 406 | // strips literal tags here and the value is also escaped with esc_html() |
| 407 | // at render time (neutralizing entity-encoded payloads like <script>). |
| 408 | if (isset($params['no_data_msg'])) { |
| 409 | $params['no_data_msg'] = sanitize_text_field($params['no_data_msg']); |
| 410 | } |
| 411 | |
| 412 | $items = isset($params['items_per_page']) && $params['items_per_page'] > 0 ? (int)$params['items_per_page'] : 20; |
| 413 | $offset = $cp = 0; |
| 414 | if (isset($params['jstable']) && (int)$params['jstable'] === 1) { |
| 415 | $items = 2000; |
| 416 | } else { |
| 417 | $cp = wpdm_query_var('cp', ['validate' => 'int', 'default' => 1]); |
| 418 | $offset = ($cp - 1) * $items; |
| 419 | |
| 420 | } |
| 421 | $terms = isset($params['categories']) ? explode(",", $params['categories']) : array(); |
| 422 | $tag = isset($params['tag']) ? $params['tag'] : ''; |
| 423 | if (isset($_GET['wpdmc'])) $terms = array(wpdm_query_var('wpdmc', 'txt')); |
| 424 | $total_files = wp_count_posts('wpdmpro')->publish; |
| 425 | if (count($terms) > 0) { |
| 426 | $tax_query = array(array( |
| 427 | 'taxonomy' => 'wpdmcategory', |
| 428 | 'field' => 'slug', |
| 429 | 'terms' => $terms, |
| 430 | 'operator' => 'IN', |
| 431 | 'include_children' => false |
| 432 | )); |
| 433 | } |
| 434 | if ($tag != '') { |
| 435 | $params['tag'] = $tag; |
| 436 | } |
| 437 | if (isset($params['login']) && $params['login'] == 1 && !is_user_logged_in()) |
| 438 | return WPDM()->user->login->form($params); |
| 439 | else { |
| 440 | ob_start(); |
| 441 | //include(wpdm_tpl_path("wpdm-all-downloads.php")); |
| 442 | include Template::locate("all-packages-shortcode.php", __DIR__.'/views'); |
| 443 | $data = ob_get_clean(); |
| 444 | return $data; |
| 445 | } |
| 446 | } |
| 447 | |
| 448 | /** |
| 449 | * Display package changelog with a modern timeline UI |
| 450 | * |
| 451 | * Shortcode: [wpdm_changelog] |
| 452 | * |
| 453 | * @since 6.0 |
| 454 | * |
| 455 | * @param array $params { |
| 456 | * Shortcode attributes. |
| 457 | * |
| 458 | * @type int $id Required. The package/post ID. |
| 459 | * @type string $title Optional. Header title displayed above the changelog. |
| 460 | * Default: 'Changelog' |
| 461 | * @type bool $show_empty Optional. Whether to show a message when no changelog exists. |
| 462 | * Default: false |
| 463 | * @type int $limit Optional. Maximum number of entries to display. |
| 464 | * Use 0 to show all entries. Default: 0 |
| 465 | * @type bool $collapsed Optional. Whether to collapse all entries except the first (latest). |
| 466 | * Default: true |
| 467 | * } |
| 468 | * |
| 469 | * @return string HTML output of the changelog timeline, or empty string if no ID provided. |
| 470 | * |
| 471 | * Usage Examples: |
| 472 | * |
| 473 | * Basic usage (package ID required): |
| 474 | * [wpdm_changelog id="123"] |
| 475 | * |
| 476 | * Custom title: |
| 477 | * [wpdm_changelog id="123" title="Version History"] |
| 478 | * |
| 479 | * Show all entries expanded: |
| 480 | * [wpdm_changelog id="123" collapsed="false"] |
| 481 | * |
| 482 | * Limit to latest 5 entries: |
| 483 | * [wpdm_changelog id="123" limit="5"] |
| 484 | * |
| 485 | * Show message when no changelog exists: |
| 486 | * [wpdm_changelog id="123" show_empty="true"] |
| 487 | * |
| 488 | * Combined parameters: |
| 489 | * [wpdm_changelog id="123" title="Release Notes" limit="10" collapsed="true"] |
| 490 | */ |
| 491 | function changelog($params) { |
| 492 | if(!isset($params['id'])) return ''; |
| 493 | return WPDM()->package->changelog($params['id'], $params); |
| 494 | } |
| 495 | |
| 496 | } |
| 497 | |
| 498 |