Skip to content

Instantly share code, notes, and snippets.

@Exieros
Last active May 22, 2022 22:34
Show Gist options
  • Select an option

  • Save Exieros/64db3c7404f98f0beb75b007cb16d04a to your computer and use it in GitHub Desktop.

Select an option

Save Exieros/64db3c7404f98f0beb75b007cb16d04a to your computer and use it in GitHub Desktop.
<?php
/*
* Счетчик скачиваний файлов по attach-id.
* Скачивания будут учитываться если скачивать attach по ссылке вида site.ru/download/{id}
* Чтобы получить кол-во скачиваний вызвать функцию Downloader::get_count($id);
*/
namespace Exieros\Utils;
class Downloader {
private const TABLE = 'downloads';
protected static string $table;
protected static string $link_base = '/download/';
public function __construct() {
global $wpdb;
self::$table = $wpdb->prefix . self::TABLE;
add_action( 'init', [ $this, 'rewrite_download_link' ] );
$query = $wpdb->prepare( 'SHOW TABLES LIKE %s', self::$table );
if ( $wpdb->get_var( $query ) !== self::$table ) {
$table_name = self::$table;
$wpdb->query(<<<SQL
CREATE TABLE `{$table_name}` (
`id` bigint(20) UNSIGNED NOT NULL,
`count` bigint(20) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SQL);
}
}
/**
* Получить кол-во скачиваний по attachment-id
* @param int $id attachment id.
* @return int
*/
public static function get_count( int $id ): int {
global $wpdb;
$record = $wpdb->get_row(
$wpdb->prepare( "SELECT count FROM {$wpdb->prefix}downloads WHERE id = %s", $id )
);
return $record->count ?? - 1;
}
/**
* Создать запись в таблице скачиваний по attachment-id
* @param int $id Attachment id
*/
public static function create( int $id ): void {
global $wpdb;
$wpdb->insert( self::$table, [
'count' => 1,
'id' => $id,
] );
}
public function rewrite_download_link(): void {
$uri = '';
if ( isset( $_SERVER['REQUEST_URI'] ) ) {
$uri = filter_var( wp_unslash( $_SERVER['REQUEST_URI'] ), FILTER_SANITIZE_STRING );
}
$path = wp_parse_url( $uri, PHP_URL_PATH );
if (str_starts_with(trailingslashit($path), self::$link_base)) {
$download_link = untrailingslashit( $path );
$id = (int) str_replace(self::$link_base, '', $download_link);
if($id === 0 ){
return;
}
$real_path = get_attached_file($id);
if($real_path===''){
return;
}
$this->increment_count( $id );
self::download_file($id);
}
}
/**
* Скачать файл по attachment-id
* @param int $id attachment id
*/
private static function download_file( int $id ): void {
if ( ! $id ) {
return;
}
$file_path = get_attached_file($id);
if ( !$file_path ) {
return;
}
$file_name = rawurlencode( pathinfo( $file_path, PATHINFO_FILENAME ) );
$file_extension = rawurlencode( pathinfo( $file_path, PATHINFO_EXTENSION ) );
$file_size = filesize( $file_path );
$known_content_types = [
'html' => 'text/html',
'htm' => 'text/html',
'txt' => 'text/plain',
'jpg' => 'image/jpg',
'jpeg' => 'image/jpg',
'png' => 'image/png',
'gif' => 'image/gif',
'tiff' => 'image/tiff',
'pdf' => 'application/pdf',
'doc' => 'application/msword',
'docx' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'xlsx' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'pptx' => 'application/vnd.ms-powerpoint',
'php' => 'text/plain',
'exe' => 'application/octet-stream',
'zip' => 'application/zip',
];
$content_type = 'application/force-download';
if ( array_key_exists( $file_extension, $known_content_types ) ) {
$content_type = $known_content_types[ $file_extension ];
}
header( 'Expires: 0' );
header( 'Cache-Control: no-cache, no-store, must-revalidate' );
header( 'Cache-Control: pre-check=0, post-check=0, max-age=0', false );
header( 'Pragma: no-cache' );
header( "Content-type: {$content_type}" );
header( "Content-Disposition:attachment; filename={$file_name}.{$file_extension}" );
header( 'Content-Transfer-Encoding: binary' );
header( "Content-Length: {$file_size}" );
readfile( $file_path );
exit();
}
/**
* Увеличить счетчик скачивания на единицу
* @param int $id
*/
private function increment_count( int $id ): void {
global $wpdb;
$count = self::get_count( $id );
if($count === -1){
self::create($id);
}else {
$wpdb->update(self::$table, ['count' => ++$count], ['id' => $id]);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment