Plugin Directory

Changeset 3448768


Ignore:
Timestamp:
01/28/2026 02:14:29 PM (6 weeks ago)
Author:
codeconfig
Message:

Code cleanup

Location:
integrate-dropbox
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • integrate-dropbox/tags/1.3.4/models/Files.php

    r3448719 r3448768  
    99use CodeConfig\IDB\Utils\MimeTypeManager;
    1010use CodeConfig\IDB\Utils\Singleton;
     11use WP_Error;
     12
    1113use function count;
    1214use function in_array;
    1315use function intval;
    1416use function is_array;
    15 use WP_Error;
    16 class Files extends BaseModel {
     17
     18class Files extends BaseModel
     19{
    1720    use Singleton;
    1821    public const TABLE_NAME = 'ccpidb_files';
     
    5659    public const META_DATA = ['attachmentId', 'mediaInfo', 'childCount'];
    5760
    58     public function __construct() {
    59         parent::__construct( self::TABLE_NAME );
     61    public function __construct()
     62    {
     63        parent::__construct(self::TABLE_NAME);
    6064        // $this->getChildPathsWithThumbnails(['7618d90767fefcb7d21109071e707ae1'], 'id:XR5DPLkvVHQAAAAAAAADAA');
    6165        // $this->getChildPathsWithThumbnails(['7618d90767fefcb7d21109071e707ae1'], 'id:XR5DPLkvVHQAAAAAAAADAA');
     
    7175     * @return array|null|WP_Error An array of processed file data from the specified folder.
    7276     */
    73     public function getFolder( $folderKey, $config = [] ) {
     77    public function getFolder($folderKey, $config = [])
     78    {
    7479        global $wpdb;
    7580        $allowedOrderBy = [
     
    7984            'size'
    8085        ];
    81         $order = $this->sanitizeOrder( $config['order'] ?? 'DESC' );
    82         $orderBy = $this->sanitizeOrderBy( $config['orderBy'] ?? 'createdAt', $allowedOrderBy );
    83         $page = ( isset( $config['page'] ) ? (int) $config['page'] : 1 );
    84         $perPage = ( isset( $config['perPage'] ) ? (int) $config['perPage'] : 20 );
    85         $pagination = $this->sanitizePagination( $page, $perPage );
    86         if ( $folderKey !== '/' ) {
    87             $file = $this->getFile( $folderKey );
    88             if ( $file instanceof File === false || is_wp_error( $file ) ) {
    89                 return new WP_Error(404, __( 'Folder not found.', 'integrate-dropbox' ));
     86        $order = $this->sanitizeOrder($config['order'] ?? 'DESC');
     87        $orderBy = $this->sanitizeOrderBy($config['orderBy'] ?? 'createdAt', $allowedOrderBy);
     88        $page = (isset($config['page']) ? (int) $config['page'] : 1);
     89        $perPage = (isset($config['perPage']) ? (int) $config['perPage'] : 20);
     90        $pagination = $this->sanitizePagination($page, $perPage);
     91        if ($folderKey !== '/') {
     92            $file = $this->getFile($folderKey);
     93            if ($file instanceof File === false || is_wp_error($file)) {
     94                return new WP_Error(404, __('Folder not found.', 'integrate-dropbox'));
    9095            }
    9196            $accountId = $file->getAccountId();
     
    9398        } else {
    9499            $account = Accounts::getInstance()->getAccount();
    95             if ( $account instanceof Account === false || is_wp_error( $account ) ) {
    96                 return new WP_Error(404, __( 'Account not found.', 'integrate-dropbox' ));
     100            if ($account instanceof Account === false || is_wp_error($account)) {
     101                return new WP_Error(404, __('Account not found.', 'integrate-dropbox'));
    97102            }
    98103            $accountId = $account->getId();
    99104            $path = '/';
    100105        }
    101         if ( !current_user_can( 'manage_options' ) && !wp_doing_cron() ) {
    102             if ( !is_user_logged_in() ) {
    103                 return new WP_Error('unauthorized', __( 'You must be logged in to access this folder.', 'integrate-dropbox' ));
     106        if (!current_user_can('manage_options') && !wp_doing_cron()) {
     107            if (!is_user_logged_in()) {
     108                return new WP_Error('unauthorized', __('You must be logged in to access this folder.', 'integrate-dropbox'));
    104109            }
    105110            $user = wp_get_current_user();
    106             if ( !$user instanceof \WP_User ) {
    107                 return new WP_Error('unauthorized', __( 'You must be logged in to access this folder.', 'integrate-dropbox' ));
     111            if (!$user instanceof \WP_User) {
     112                return new WP_Error('unauthorized', __('You must be logged in to access this folder.', 'integrate-dropbox'));
    108113            }
    109114            $userName = $user->user_login;
    110115            $roles = $user->roles;
    111             $accessSettings = UserAccess::getInstance()->getAccessData( $userName, $roles );
    112             if ( empty( $accessSettings ) ) {
    113                 if ( !current_user_can( 'manage_options' ) ) {
    114                     return new WP_Error('forbidden', __( 'You do not have permission to access this folder.', 'integrate-dropbox' ));
     116            $accessSettings = UserAccess::getInstance()->getAccessData($userName, $roles);
     117            if (empty($accessSettings)) {
     118                if (!current_user_can('manage_options')) {
     119                    return new WP_Error('forbidden', __('You do not have permission to access this folder.', 'integrate-dropbox'));
    115120                }
    116121            } else {
    117122                $accessSettingsFolders = $accessSettings['folders'] ?? [];
    118                 if ( empty( $accessSettingsFolders ) || !is_array( $accessSettingsFolders ) ) {
    119                     return new WP_Error('forbidden', __( 'You do not have permission to access this folder.', 'integrate-dropbox' ));
     123                if (empty($accessSettingsFolders) || !is_array($accessSettingsFolders)) {
     124                    return new WP_Error('forbidden', __('You do not have permission to access this folder.', 'integrate-dropbox'));
    120125                }
    121                 if ( $folderKey === '/' ) {
    122                     $folder = $this->getFilesByKeys( $accessSettingsFolders, [
     126                if ($folderKey === '/') {
     127                    $folder = $this->getFilesByKeys($accessSettingsFolders, [
    123128                        'returnType' => 'array',
    124129                        'perPage'    => $config['perPage'],
     
    127132                        'order'      => $config['order'],
    128133                        'recursive'  => false,
    129                     ] );
     134                    ]);
    130135                    return $folder;
    131136                }
    132                 if ( !Helpers::validateFileKey( $folderKey, $accessSettingsFolders ) ) {
    133                     return new WP_Error('forbidden', __( 'You do not have permission to access this folder.', 'integrate-dropbox' ));
     137                if (!Helpers::validateFileKey($folderKey, $accessSettingsFolders)) {
     138                    return new WP_Error('forbidden', __('You do not have permission to access this folder.', 'integrate-dropbox'));
    134139                }
    135140            }
    136141        }
    137         $sql = $wpdb->prepare( "SELECT * FROM %i WHERE accountId = %s", $this->tableName, $accountId );
    138         $totalSql = $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE accountId = %s", $this->tableName, $accountId );
    139         if ( !empty( $config['search'] ) ) {
    140             $searchPattern = '%' . $wpdb->esc_like( $config['search'] ?? '' ) . '%';
    141             $searchScope = ( in_array( $config['searchScope'] ?? 'folder', ['folder', 'global'] ) ? $config['searchScope'] : 'folder' );
    142             $sql .= $wpdb->prepare( " AND name LIKE %s", $searchPattern );
    143             $totalSql .= $wpdb->prepare( " AND name LIKE %s", $searchPattern );
    144             if ( $searchScope === 'folder' ) {
    145                 $sql .= $wpdb->prepare( " AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%" );
    146                 $totalSql .= $wpdb->prepare( " AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%" );
     142        $sql = $wpdb->prepare("SELECT * FROM %i WHERE accountId = %s", $this->tableName, $accountId);
     143        $totalSql = $wpdb->prepare("SELECT COUNT(*) FROM %i WHERE accountId = %s", $this->tableName, $accountId);
     144        if (!empty($config['search'])) {
     145            $searchPattern = '%' . $wpdb->esc_like($config['search'] ?? '') . '%';
     146            $searchScope = (in_array($config['searchScope'] ?? 'folder', ['folder', 'global']) ? $config['searchScope'] : 'folder');
     147            $sql .= $wpdb->prepare(" AND name LIKE %s", $searchPattern);
     148            $totalSql .= $wpdb->prepare(" AND name LIKE %s", $searchPattern);
     149            if ($searchScope === 'folder') {
     150                $sql .= $wpdb->prepare(" AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%");
     151                $totalSql .= $wpdb->prepare(" AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%");
    147152            }
    148153        } else {
    149             if ( !empty( $config['recursive'] ) && $config['recursive'] === true ) {
    150                 $sql .= $wpdb->prepare( " AND parent LIKE %s", "{$path}%" );
    151                 $totalSql .= $wpdb->prepare( " AND parent LIKE %s", "{$path}%" );
     154            if (!empty($config['recursive']) && $config['recursive'] === true) {
     155                $sql .= $wpdb->prepare(" AND parent LIKE %s", "{$path}%");
     156                $totalSql .= $wpdb->prepare(" AND parent LIKE %s", "{$path}%");
    152157            } else {
    153                 $sql .= $wpdb->prepare( " AND parent = %s", $path );
    154                 $totalSql .= $wpdb->prepare( " AND parent = %s", $path );
    155             }
    156         }
    157         if ( !empty( $config['types'] ) && is_array( $config['types'] ) ) {
     158                $sql .= $wpdb->prepare(" AND parent = %s", $path);
     159                $totalSql .= $wpdb->prepare(" AND parent = %s", $path);
     160            }
     161        }
     162        if (!empty($config['types']) && is_array($config['types'])) {
    158163            $types = $config['types'];
    159             $extensions = MimeTypeManager::getExtensionsByCategory( $types );
    160             $placeholders = implode( ',', array_fill( 0, count( $extensions ), '%s' ) );
    161             $sql .= $wpdb->prepare( " AND `extension` IN ({$placeholders})", $extensions );
    162             $totalSql .= $wpdb->prepare( " AND `extension` IN ({$placeholders})", $extensions );
     164            $extensions = MimeTypeManager::getExtensionsByCategory($types);
     165            $placeholders = implode(',', array_fill(0, count($extensions), '%s'));
     166            $sql .= $wpdb->prepare(" AND `extension` IN ({$placeholders})", $extensions);
     167            $totalSql .= $wpdb->prepare(" AND `extension` IN ({$placeholders})", $extensions);
    163168        }
    164169        $sql .= $wpdb->prepare(
     
    168173            $pagination['offset']
    169174        );
    170         $cache_key = "ccpidb_folder_" . md5( $sql );
    171         $cache_group = "ccpidb_files_" . md5( "{$path}_{$accountId}" );
    172         $files = wp_cache_get( $cache_key, $cache_group );
    173         if ( $files !== false ) {
     175        $cache_key = "ccpidb_folder_" . md5($sql);
     176        $cache_group = "ccpidb_files_" . md5("{$path}_{$accountId}");
     177        $files = wp_cache_get($cache_key, $cache_group);
     178        if ($files !== false) {
    174179            return $files;
    175180        }
    176181        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    177         $files = $wpdb->get_results( $sql );
     182        $files = $wpdb->get_results($sql);
    178183        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    179         $total = $wpdb->get_var( $totalSql );
    180         if ( empty( $files ) || is_wp_error( $files ) ) {
     184        $total = $wpdb->get_var($totalSql);
     185        if (empty($files) || is_wp_error($files)) {
    181186            $files = [];
    182187        }
    183         $processedFiles = $this->processFiles( $files );
    184         $totalPages = ceil( $total / $perPage );
     188        $processedFiles = $this->processFiles($files);
     189        $totalPages = ceil($total / $perPage);
    185190        $hasMore = $totalPages > $page;
    186191        $response = [
    187             'breadcrumb'  => array_reverse( $this->getBreadcrumbByKey( $folderKey ) ),
    188             'totalPage'   => ( $totalPages < 1 ? 1 : $totalPages ),
     192            'breadcrumb'  => array_reverse($this->getBreadcrumbByKey($folderKey)),
     193            'totalPage'   => ($totalPages < 1 ? 1 : $totalPages),
    189194            'hasMore'     => $hasMore,
    190195            'currentPage' => $page,
    191196            'files'       => $processedFiles,
    192             'totalFiles'  => intval( $total ),
    193         ];
    194         if ( $hasMore ) {
     197            'totalFiles'  => intval($total),
     198        ];
     199        if ($hasMore) {
    195200            $response['nextPage'] = $page + 1;
    196201        }
    197         if ( !empty( $processedFiles ) ) {
     202        if (!empty($processedFiles)) {
    198203            wp_cache_set(
    199204                $cache_key,
     
    219224     * @return \CodeConfig\IDB\App\File|array|false The processed file data if found, otherwise null.
    220225     */
    221     public function getFile( $fileKey, $returnType = 'object' ) {
     226    public function getFile($fileKey, $returnType = 'object')
     227    {
    222228        global $wpdb;
    223229        // if ($this->isValidAccount($accountId) === false) {
     
    226232        // $file = $this->fetch("SELECT * FROM {$this->tableName} WHERE id = %s AND accountId = %s", [$id, $accountId]);
    227233        $cache_key = "ccpidb_file_{$fileKey}_{$returnType}";
    228         $file = wp_cache_get( $cache_key, 'ccpidb_files' );
    229         if ( $file !== false ) {
     234        $file = wp_cache_get($cache_key, 'ccpidb_files');
     235        if ($file !== false) {
    230236            return $file;
    231237        }
    232238        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
    233         $file = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    234         if ( empty( $file ) || is_wp_error( $file ) ) {
    235             return false;
    236         }
    237         $processedFile = $this->processFile( $file, $returnType );
    238         if ( !empty( $processedFile ) ) {
    239             wp_cache_set( $cache_key, $processedFile, 'ccpidb_files' );
     239        $file = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     240        if (empty($file) || is_wp_error($file)) {
     241            return false;
     242        }
     243        $processedFile = $this->processFile($file, $returnType);
     244        if (!empty($processedFile)) {
     245            wp_cache_set($cache_key, $processedFile, 'ccpidb_files');
    240246        }
    241247        return $processedFile;
    242248    }
    243249
    244     private function getFileByPath( $path, $accountId, $returnType = 'object' ) {
     250    private function getFileByPath($path, $accountId, $returnType = 'object')
     251    {
    245252        global $wpdb;
    246253        $cache_key = "ccpidb_file_{$path}_{$accountId}";
    247         $file = wp_cache_get( $cache_key, 'ccpidb_files' );
    248         if ( $file !== false ) {
     254        $file = wp_cache_get($cache_key, 'ccpidb_files');
     255        if ($file !== false) {
    249256            return $file;
    250257        }
    251         $file = $wpdb->get_row( $wpdb->prepare(
     258        $file = $wpdb->get_row($wpdb->prepare(
    252259            "SELECT * FROM %i WHERE path = %s AND accountId = %s",
    253260            $this->tableName,
    254261            $path,
    255262            $accountId
    256         ) );
    257         $processedFile = $this->processFile( $file, $returnType );
    258         if ( !empty( $processedFile ) ) {
    259             wp_cache_set( $cache_key, $processedFile, 'ccpidb_files' );
     263        ));
     264        $processedFile = $this->processFile($file, $returnType);
     265        if (!empty($processedFile)) {
     266            wp_cache_set($cache_key, $processedFile, 'ccpidb_files');
    260267        }
    261268        return $processedFile;
    262269    }
    263270
    264     public function getFilesByKeys( array $keys, array $args = [] ) {
    265         if ( empty( $keys ) ) {
     271    public function getFilesByKeys(array $keys, array $args = [])
     272    {
     273        if (empty($keys)) {
    266274            return [];
    267275        }
     
    279287            'accountId'      => '',
    280288        ];
    281         $args = wp_parse_args( $args, $defaults );
     289        $args = wp_parse_args($args, $defaults);
    282290        $recursive = $args['recursive'];
    283291        $moduleType = $args['moduleType'] ?? '';
    284292        $accountId = $args['accountId'] ?? null;
    285         if ( 'search-box' === $moduleType && empty( $args['search'] ) && $recursive && ($args['fileKey'] ?? '') !== '/' ) {
     293        if ('search-box' === $moduleType && empty($args['search']) && $recursive && ($args['fileKey'] ?? '') !== '/') {
    286294            $moduleType = 'file-browser';
    287295        }
     
    296304        $applyNamesFilter = $args['applyNameFilter'] ?? [];
    297305        $types = $args['types'] ?? [];
    298         $extensions = ccpidbGetAllowedModuleExtensions( $moduleType );
    299         $allowedExtensions = $this->processExtensions( $extensions, $additionalExtensions, $extensionsFilterType );
    300         ob_start();
    301         echo '<pre>';
    302         var_dump( $accountId );
    303         echo '</pre>';
    304         error_log( ob_get_clean() );
    305         $filesData = $this->getFileAttributesByKeys( $keys, [
     306        $extensions = ccpidbGetAllowedModuleExtensions($moduleType);
     307        $allowedExtensions = $this->processExtensions($extensions, $additionalExtensions, $extensionsFilterType);
     308
     309        $filesData = $this->getFileAttributesByKeys($keys, [
    306310            'id',
    307311            'path',
     
    309313            'name',
    310314            'isDir'
    311         ], $accountId );
    312         if ( is_wp_error( $filesData ) || empty( $filesData ) ) {
    313             return ( $filesData ?: [] );
    314         }
    315         if ( empty( $filesData ) ) {
     315        ], $accountId);
     316        if (is_wp_error($filesData) || empty($filesData)) {
     317            return ($filesData ?: []);
     318        }
     319        if (empty($filesData)) {
    316320            return [];
    317321        }
    318         $paths = array_filter( array_map( fn( $file ) => $file['path'] ?? null, $filesData ) );
    319         if ( empty( $paths ) ) {
     322        $paths = array_filter(array_map(fn ($file) => $file['path'] ?? null, $filesData));
     323        if (empty($paths)) {
    320324            return [];
    321325        }
    322326        global $wpdb;
    323         $sql = $wpdb->prepare( "SELECT * FROM %i WHERE 1 = 1", $this->tableName );
    324         $totalSql = $wpdb->prepare( "SELECT COUNT(*) as count FROM %i WHERE 1 = 1", $this->tableName );
    325         if ( !empty( $search ) ) {
     327        $sql = $wpdb->prepare("SELECT * FROM %i WHERE 1 = 1", $this->tableName);
     328        $totalSql = $wpdb->prepare("SELECT COUNT(*) as count FROM %i WHERE 1 = 1", $this->tableName);
     329        if (!empty($search)) {
    326330            $searchPath = [];
    327             if ( $searchScope === 'global' ) {
    328                 foreach ( $filesData as $file ) {
    329                     $searchPath[] = $this->getSuccessors( $file['path'], $file['accountId'] );
     331            if ($searchScope === 'global') {
     332                foreach ($filesData as $file) {
     333                    $searchPath[] = $this->getSuccessors($file['path'], $file['accountId']);
    330334                }
    331                 $paths = array_merge( ...$searchPath );
    332             }
    333             if ( empty( $paths ) ) {
     335                $paths = array_merge(...$searchPath);
     336            }
     337            if (empty($paths)) {
    334338                return [];
    335339            }
    336             $placeholders = implode( ',', array_fill( 0, count( $paths ), '%s' ) );
    337             if ( $searchScope === 'global' ) {
    338                 $sql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, $paths, ["%{$search}%"] ) );
    339                 $totalSql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, $paths, ["%{$search}%"] ) );
     340            $placeholders = implode(',', array_fill(0, count($paths), '%s'));
     341            if ($searchScope === 'global') {
     342                $sql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, $paths, ["%{$search}%"]));
     343                $totalSql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, $paths, ["%{$search}%"]));
    340344            } else {
    341                 $sql .= $wpdb->prepare( " AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, ["%{$search}%"] ) );
    342                 $totalSql .= $wpdb->prepare( " AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, ["%{$search}%"] ) );
    343             }
    344         } elseif ( $recursive ) {
    345             $placeholders = implode( ',', array_fill( 0, count( $paths ), '%s' ) );
    346             if ( $moduleType === 'file-browser' ) {
    347                 $sql .= $wpdb->prepare( " AND `parent` IN ({$placeholders})", $paths );
    348                 $totalSql .= $wpdb->prepare( " AND `parent` IN ({$placeholders})", $paths );
    349             } elseif ( $moduleType === 'file-uploader' ) {
    350                 $uploadKeys = json_decode( sanitize_text_field( wp_unslash( $_COOKIE["ccpidb_file_uploader_files_{$shortcodeId}"] ?? '' ) ), true );
    351                 if ( empty( $uploadKeys ) || !is_array( $uploadKeys ) ) {
     345                $sql .= $wpdb->prepare(" AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, ["%{$search}%"]));
     346                $totalSql .= $wpdb->prepare(" AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, ["%{$search}%"]));
     347            }
     348        } elseif ($recursive) {
     349            $placeholders = implode(',', array_fill(0, count($paths), '%s'));
     350            if ($moduleType === 'file-browser') {
     351                $sql .= $wpdb->prepare(" AND `parent` IN ({$placeholders})", $paths);
     352                $totalSql .= $wpdb->prepare(" AND `parent` IN ({$placeholders})", $paths);
     353            } elseif ($moduleType === 'file-uploader') {
     354                $uploadKeys = json_decode(sanitize_text_field(wp_unslash($_COOKIE["ccpidb_file_uploader_files_{$shortcodeId}"] ?? '')), true);
     355                if (empty($uploadKeys) || !is_array($uploadKeys)) {
    352356                    return [];
    353357                }
    354                 $uploadKeysPlaceholders = implode( ',', array_fill( 0, count( $uploadKeys ), '%s' ) );
    355                 $sql .= $wpdb->prepare( " AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge( $paths, $uploadKeys ) );
    356                 $totalSql .= $wpdb->prepare( " AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge( $paths, $uploadKeys ) );
     358                $uploadKeysPlaceholders = implode(',', array_fill(0, count($uploadKeys), '%s'));
     359                $sql .= $wpdb->prepare(" AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge($paths, $uploadKeys));
     360                $totalSql .= $wpdb->prepare(" AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge($paths, $uploadKeys));
    357361            } else {
    358                 $sql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths );
    359                 $totalSql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths );
     362                $sql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths);
     363                $totalSql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths);
    360364                // foreach ($paths as $path) {
    361365                //     $sql      .= $wpdb->prepare(" AND (`path` LIKE %s OR `parent` LIKE %s)", "$path%", "$path%");
     
    364368            }
    365369        } else {
    366             if ( !empty( $allowedExtensions ) && !in_array( 'folder', $allowedExtensions ) ) {
     370            if (!empty($allowedExtensions) && !in_array('folder', $allowedExtensions)) {
    367371                $allowedExtensions[] = 'folder';
    368372            }
    369             $placeholders = implode( ',', array_fill( 0, count( $paths ), '%s' ) );
    370             $sql .= $wpdb->prepare( " AND `path` IN ({$placeholders})", $paths );
    371             $totalSql .= $wpdb->prepare( " AND `path` IN ({$placeholders})", $paths );
    372         }
    373         if ( !empty( $types ) && is_array( $types ) ) {
    374             $extensions = MimeTypeManager::getExtensionsByCategory( $types );
    375             $extPlaceholders = implode( ',', array_fill( 0, count( $extensions ), '%s' ) );
    376             $sql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $extensions );
    377             $totalSql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $extensions );
    378         }
    379         if ( !empty( $allowedExtensions ) ) {
    380             $extPlaceholders = implode( ',', array_fill( 0, count( $allowedExtensions ), '%s' ) );
    381             $sql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $allowedExtensions );
    382             $totalSql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $allowedExtensions );
    383         }
    384         if ( !empty( $args['orderBy'] ) && !empty( $args['order'] ) ) {
     373            $placeholders = implode(',', array_fill(0, count($paths), '%s'));
     374            $sql .= $wpdb->prepare(" AND `path` IN ({$placeholders})", $paths);
     375            $totalSql .= $wpdb->prepare(" AND `path` IN ({$placeholders})", $paths);
     376        }
     377        if (!empty($types) && is_array($types)) {
     378            $extensions = MimeTypeManager::getExtensionsByCategory($types);
     379            $extPlaceholders = implode(',', array_fill(0, count($extensions), '%s'));
     380            $sql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $extensions);
     381            $totalSql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $extensions);
     382        }
     383        if (!empty($allowedExtensions)) {
     384            $extPlaceholders = implode(',', array_fill(0, count($allowedExtensions), '%s'));
     385            $sql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $allowedExtensions);
     386            $totalSql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $allowedExtensions);
     387        }
     388        if (!empty($args['orderBy']) && !empty($args['order'])) {
    385389            $allowedOrderBy = [
    386390                'id',
     
    390394                'updatedAt'
    391395            ];
    392             $orderBy = $this->sanitizeOrderBy( $args['orderBy'], $allowedOrderBy );
    393             $order = $this->sanitizeOrder( $args['order'] );
    394             $offset = $this->sanitizePagination( $args['page'], $args['perPage'] );
    395             $sql .= $wpdb->prepare( " ORDER BY (CASE WHEN extension = 'folder' THEN 0 ELSE 1 END), `{$orderBy}` {$order} LIMIT %d OFFSET %d", $offset['perPage'], $offset['offset'] );
     396            $orderBy = $this->sanitizeOrderBy($args['orderBy'], $allowedOrderBy);
     397            $order = $this->sanitizeOrder($args['order']);
     398            $offset = $this->sanitizePagination($args['page'], $args['perPage']);
     399            $sql .= $wpdb->prepare(" ORDER BY (CASE WHEN extension = 'folder' THEN 0 ELSE 1 END), `{$orderBy}` {$order} LIMIT %d OFFSET %d", $offset['perPage'], $offset['offset']);
    396400        }
    397401        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    398         $files = $wpdb->get_results( $sql );
     402        $files = $wpdb->get_results($sql);
    399403        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    400         $totalCount = $wpdb->get_row( $totalSql );
    401         if ( empty( $files ) || is_wp_error( $files ) || is_wp_error( $totalCount ) ) {
     404        $totalCount = $wpdb->get_row($totalSql);
     405        if (empty($files) || is_wp_error($files) || is_wp_error($totalCount)) {
    402406            return [];
    403407        }
    404         $files = $this->processFiles( $files, $returnType );
    405         $totalFiles = ( isset( $totalCount->count ) ? (int) $totalCount->count : count( $files ) );
     408        $files = $this->processFiles($files, $returnType);
     409        $totalFiles = (isset($totalCount->count) ? (int) $totalCount->count : count($files));
    406410        $page = $offset['page'] ?? 1;
    407         $totalPage = ceil( $totalFiles / ($offset['perPage'] ?? 1) );
     411        $totalPage = ceil($totalFiles / ($offset['perPage'] ?? 1));
    408412        $response = [
    409413            'breadcrumb'  => [[
    410414                'fileKey' => '/',
    411                 'name'    => __( 'Home', 'integrate-dropbox' ),
     415                'name'    => __('Home', 'integrate-dropbox'),
    412416            ]],
    413             'totalPage'   => ( $totalPage < 1 ? 1 : $totalPage ),
     417            'totalPage'   => ($totalPage < 1 ? 1 : $totalPage),
    414418            'hasMore'     => $totalPage > $page,
    415419            'currentPage' => $page,
     
    417421            'totalFiles'  => $totalFiles,
    418422        ];
    419         if ( $response['hasMore'] ) {
     423        if ($response['hasMore']) {
    420424            $response['nextPage'] = $page + 1;
    421425        }
     
    423427    }
    424428
    425     public function getFolderTree( $accountId, ... $rootPaths ) {
     429    public function getFolderTree($accountId, ... $rootPaths)
     430    {
    426431        global $wpdb;
    427432        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
    428         $sql = $wpdb->prepare( "SELECT fileKey, name, parent, path FROM %i WHERE `extension` = 'folder' AND accountId = %s", $this->tableName, $accountId );
    429         if ( !empty( $rootPaths ) && !in_array( '/', $rootPaths, true ) ) {
     433        $sql = $wpdb->prepare("SELECT fileKey, name, parent, path FROM %i WHERE `extension` = 'folder' AND accountId = %s", $this->tableName, $accountId);
     434        if (!empty($rootPaths) && !in_array('/', $rootPaths, true)) {
    430435            $sql .= " AND ( 0=1 ";
    431             foreach ( $rootPaths as $rootPath ) {
    432                 $sql .= $wpdb->prepare( " OR path LIKE %s OR path LIKE %s", "{$rootPath}/%", "{$rootPath}" );
     436            foreach ($rootPaths as $rootPath) {
     437                $sql .= $wpdb->prepare(" OR path LIKE %s OR path LIKE %s", "{$rootPath}/%", "{$rootPath}");
    433438            }
    434439            $sql .= " ) ";
    435440        }
    436         $files = $wpdb->get_results( $sql, ARRAY_A );
    437         if ( empty( $files ) || is_wp_error( $files ) ) {
     441        $files = $wpdb->get_results($sql, ARRAY_A);
     442        if (empty($files) || is_wp_error($files)) {
    438443            return [];
    439444        }
    440         return $this->processFolderTree( $files, $rootPaths );
    441     }
    442 
    443     public function addFile( array $data ) {
     445        return $this->processFolderTree($files, $rootPaths);
     446    }
     447
     448    public function addFile(array $data)
     449    {
    444450        global $wpdb;
    445451        $file = [
     
    448454            'path'            => $data['path'] ?? '',
    449455            'name'            => $data['name'] ?? null,
    450             'size'            => intval( $data['size'] ?? 0 ),
     456            'size'            => intval($data['size'] ?? 0),
    451457            'parent'          => $data['parent'] ?? null,
    452458            'accountId'       => $data['accountId'] ?? '',
     
    457463            'sharedLink'      => $data['sharedLink'] ?? null,
    458464            'isDir'           => $data['isDir'] ?? null,
    459             'permissions'     => maybe_serialize( $data['permissions'] ?? [] ),
     465            'permissions'     => maybe_serialize($data['permissions'] ?? []),
    460466            'hasOwnThumbnail' => $data['hasOwnThumbnail'] ?? null,
    461467            'icon'            => $data['icon'] ?? null,
    462             'additionalData'  => maybe_serialize( $data['additionalData'] ?? [] ),
    463             'createdAt'       => current_time( 'mysql' ),
    464             'updatedAt'       => current_time( 'mysql' ),
    465         ];
    466         if ( empty( $file['fileId'] ) || empty( $file['accountId'] ) ) {
    467             return new WP_Error(404, __( 'Missing file ID or account ID.', 'integrate-dropbox' ));
     468            'additionalData'  => maybe_serialize($data['additionalData'] ?? []),
     469            'createdAt'       => current_time('mysql'),
     470            'updatedAt'       => current_time('mysql'),
     471        ];
     472        if (empty($file['fileId']) || empty($file['accountId'])) {
     473            return new WP_Error(404, __('Missing file ID or account ID.', 'integrate-dropbox'));
    468474        }
    469475        $format = [
     
    506512            '%s',
    507513        ];
    508         if ( !empty( $data['thumbnailRatio'] ) ) {
     514        if (!empty($data['thumbnailRatio'])) {
    509515            $file['thumbnailRatio'] = $data['thumbnailRatio'];
    510516            $format[] = '%s';
    511517            // thumbnailRatio
    512518        }
    513         if ( $this->isCachedFile( $file["fileKey"] ) ) {
     519        if ($this->isCachedFile($file["fileKey"])) {
    514520            unset($file["id"]);
    515521            unset($file["fileId"]);
     
    549555                '%s',
    550556            ];
    551             if ( !empty( $data['thumbnailRatio'] ) ) {
     557            if (!empty($data['thumbnailRatio'])) {
    552558                $updateFormat[] = '%s';
    553559                // thumbnailRatio
     
    563569            );
    564570        }
    565         return $wpdb->insert( $this->tableName, $file, $format );
    566     }
    567 
    568     public function deleteFiles( $fileKeys ) : int {
    569         global $wpdb;
    570         if ( empty( $fileKeys ) ) {
     571        return $wpdb->insert($this->tableName, $file, $format);
     572    }
     573
     574    public function deleteFiles($fileKeys): int
     575    {
     576        global $wpdb;
     577        if (empty($fileKeys)) {
    571578            return 0;
    572579        }
    573580        $fileKeys = (array) $fileKeys;
    574         $files = $this->getFileAttributesByKeys( $fileKeys, ['accountId', 'path', 'isDir'] );
    575         if ( empty( $files ) ) {
     581        $files = $this->getFileAttributesByKeys($fileKeys, ['accountId', 'path', 'isDir']);
     582        if (empty($files)) {
    576583            return 0;
    577584        }
    578585        $filePaths = [];
    579586        $folderRefs = [];
    580         foreach ( $files as $file ) {
    581             if ( empty( $file['path'] ) || empty( $file['accountId'] ) ) {
     587        foreach ($files as $file) {
     588            if (empty($file['path']) || empty($file['accountId'])) {
    582589                continue;
    583590            }
    584             if ( !empty( $file['isDir'] ) ) {
     591            if (!empty($file['isDir'])) {
    585592                $folderRefs[] = [$file['path'], $file['accountId']];
    586593            } else {
     
    588595            }
    589596        }
    590         foreach ( $folderRefs as [$path, $accountId] ) {
    591             $filePaths = array_merge( $filePaths, (array) $this->getSuccessors( $path, $accountId ) );
    592         }
    593         if ( empty( $filePaths ) ) {
     597        foreach ($folderRefs as [$path, $accountId]) {
     598            $filePaths = array_merge($filePaths, (array) $this->getSuccessors($path, $accountId));
     599        }
     600        if (empty($filePaths)) {
    594601            return 0;
    595602        }
    596         $placeholders = implode( ',', array_fill( 0, count( $filePaths ), '%s' ) );
    597         return (int) $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE path IN ({$placeholders}) OR parent IN ({$placeholders})", array_merge( [$this->tableName], $filePaths, $filePaths ) ) );
    598     }
    599 
    600     public function deleteFilesByAccount( $accountId ) {
    601         if ( empty( $accountId ) ) {
     603        $placeholders = implode(',', array_fill(0, count($filePaths), '%s'));
     604        return (int) $wpdb->query($wpdb->prepare("DELETE FROM %i WHERE path IN ({$placeholders}) OR parent IN ({$placeholders})", array_merge([$this->tableName], $filePaths, $filePaths)));
     605    }
     606
     607    public function deleteFilesByAccount($accountId)
     608    {
     609        if (empty($accountId)) {
    602610            return 0;
    603611        }
    604         return $this->deleteRecords( [
     612        return $this->deleteRecords([
    605613            'accountId' => $accountId,
    606         ] );
    607     }
    608 
    609     public function isCachedFile( $fileKey ) {
    610         global $wpdb;
    611         $folder = $wpdb->get_row( $wpdb->prepare( "SELECT fileKey FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    612         return !empty( $folder );
    613     }
    614 
    615     public function getPathById( $fileId ) {
    616         global $wpdb;
    617         $file = $wpdb->get_row( $wpdb->prepare( "SELECT path FROM %i WHERE fileId = %s", $this->tableName, $fileId ) );
    618         if ( empty( $file ) || is_wp_error( $file ) ) {
     614        ]);
     615    }
     616
     617    public function isCachedFile($fileKey)
     618    {
     619        global $wpdb;
     620        $folder = $wpdb->get_row($wpdb->prepare("SELECT fileKey FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     621        return !empty($folder);
     622    }
     623
     624    public function getPathById($fileId)
     625    {
     626        global $wpdb;
     627        $file = $wpdb->get_row($wpdb->prepare("SELECT path FROM %i WHERE fileId = %s", $this->tableName, $fileId));
     628        if (empty($file) || is_wp_error($file)) {
    619629            return false;
    620630        }
     
    622632    }
    623633
    624     public function getPathsByKeys( $fileKeys ) {
    625         global $wpdb;
    626         $isString = \is_string( $fileKeys );
    627         if ( $isString ) {
     634    public function getPathsByKeys($fileKeys)
     635    {
     636        global $wpdb;
     637        $isString = \is_string($fileKeys);
     638        if ($isString) {
    628639            $fileKeys = [$fileKeys];
    629640        }
    630         $placeholders = implode( ',', array_fill( 0, count( $fileKeys ), '%s' ) );
    631         $preparedQuery = $wpdb->prepare( "SELECT path FROM %i WHERE fileKey IN ({$placeholders})", array_merge( [$this->tableName], $fileKeys ) );
    632         $results = $wpdb->get_results( $preparedQuery );
    633         if ( $isString && \count( $results ) === 1 ) {
     641        $placeholders = implode(',', array_fill(0, count($fileKeys), '%s'));
     642        $preparedQuery = $wpdb->prepare("SELECT path FROM %i WHERE fileKey IN ({$placeholders})", array_merge([$this->tableName], $fileKeys));
     643        $results = $wpdb->get_results($preparedQuery);
     644        if ($isString && \count($results) === 1) {
    634645            return $results[0]->path;
    635646        }
    636647        $paths = [];
    637         foreach ( $results as $row ) {
     648        foreach ($results as $row) {
    638649            $paths[] = $row->path;
    639650        }
     
    650661        global $wpdb;
    651662        // Validate inputs
    652         if ( empty( $columns ) || empty( $fileKeys ) ) {
     663        if (empty($columns) || empty($fileKeys)) {
    653664            return [];
    654665        }
    655666        // Filter and sanitize columns
    656         $sanitizedColumns = array_filter( $columns, fn( $col ) => in_array( $col, self::COLUMNS, true ) );
    657         if ( empty( $sanitizedColumns ) ) {
     667        $sanitizedColumns = array_filter($columns, fn ($col) => in_array($col, self::COLUMNS, true));
     668        if (empty($sanitizedColumns)) {
    658669            return [];
    659670        }
    660671        // Validate WHERE clause columns
    661         if ( !empty( $where ) ) {
    662             foreach ( array_keys( $where ) as $whereColumn ) {
    663                 if ( !in_array( $whereColumn, self::COLUMNS, true ) ) {
     672        if (!empty($where)) {
     673            foreach (array_keys($where) as $whereColumn) {
     674                if (!in_array($whereColumn, self::COLUMNS, true)) {
    664675                    return [];
    665676                }
     
    667678        }
    668679        // Prepare column identifiers using %i placeholders for security
    669         $columnPlaceholders = implode( ',', array_fill( 0, count( $sanitizedColumns ), '%i' ) );
    670         $keyPlaceholders = implode( ',', array_fill( 0, count( $fileKeys ), '%s' ) );
     680        $columnPlaceholders = implode(',', array_fill(0, count($sanitizedColumns), '%i'));
     681        $keyPlaceholders = implode(',', array_fill(0, count($fileKeys), '%s'));
    671682        // Build the base query with proper placeholders
    672683        $sql = "SELECT {$columnPlaceholders} FROM %i WHERE fileKey IN ({$keyPlaceholders})";
    673         $params = array_merge( $sanitizedColumns, [$this->tableName], $fileKeys );
     684        $params = array_merge($sanitizedColumns, [$this->tableName], $fileKeys);
    674685        // Add additional WHERE conditions with proper format specifiers
    675         if ( !empty( $where ) ) {
     686        if (!empty($where)) {
    676687            $whereConditions = [];
    677688            $whereIndex = 0;
    678             foreach ( $where as $column => $value ) {
     689            foreach ($where as $column => $value) {
    679690                // Use provided format or default to %s
    680                 $format = ( !empty( $where_format[$whereIndex] ) ? $where_format[$whereIndex] : '%s' );
     691                $format = (!empty($where_format[$whereIndex]) ? $where_format[$whereIndex] : '%s');
    681692                $whereConditions[] = "%i = {$format}";
    682693                $params[] = $column;
     
    684695                $whereIndex++;
    685696            }
    686             $sql .= " AND " . implode( ' AND ', $whereConditions );
    687         }
    688         $preparedQuery = $wpdb->prepare( $sql, $params );
    689         $results = $wpdb->get_results( $preparedQuery, $returnType );
    690         if ( empty( $results ) || is_wp_error( $results ) ) {
     697            $sql .= " AND " . implode(' AND ', $whereConditions);
     698        }
     699        $preparedQuery = $wpdb->prepare($sql, $params);
     700        $results = $wpdb->get_results($preparedQuery, $returnType);
     701        if (empty($results) || is_wp_error($results)) {
    691702            return [];
    692703        }
     
    694705    }
    695706
    696     public function getAccountIdByFileKey( $fileKey ) {
    697         global $wpdb;
    698         $file = $wpdb->get_row( $wpdb->prepare( "SELECT accountId FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    699         if ( empty( $file ) || is_wp_error( $file ) ) {
     707    public function getAccountIdByFileKey($fileKey)
     708    {
     709        global $wpdb;
     710        $file = $wpdb->get_row($wpdb->prepare("SELECT accountId FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     711        if (empty($file) || is_wp_error($file)) {
    700712            return false;
    701713        }
     
    703715    }
    704716
    705     public function updateThumbnail( $fileKey, $url ) {
     717    public function updateThumbnail($fileKey, $url)
     718    {
    706719        global $wpdb;
    707720        return $wpdb->update(
     
    740753        $clean = false
    741754    ) {
    742         if ( $path === '' || $path === '/' || empty( $accountId ) ) {
    743             return new WP_Error(400, __( 'Invalid path or account ID.', 'integrate-dropbox' ));
    744         }
    745         global $wpdb;
    746         if ( $clean === false ) {
    747             $file = $this->getFileByPath( $path, $accountId, 'array' );
    748             if ( is_wp_error( $file ) ) {
     755        if ($path === '' || $path === '/' || empty($accountId)) {
     756            return new WP_Error(400, __('Invalid path or account ID.', 'integrate-dropbox'));
     757        }
     758        global $wpdb;
     759        if ($clean === false) {
     760            $file = $this->getFileByPath($path, $accountId, 'array');
     761            if (is_wp_error($file)) {
    749762                return $file;
    750763            }
    751764            $existingData = $file['metaData'] ?? [];
    752             if ( is_array( $existingData ) ) {
    753                 $metaData = array_merge( $existingData, $metaData );
     765            if (is_array($existingData)) {
     766                $metaData = array_merge($existingData, $metaData);
    754767            }
    755768        }
    756769        $filteredMetaData = [];
    757         foreach ( self::META_DATA as $key ) {
    758             if ( isset( $metaData[$key] ) ) {
     770        foreach (self::META_DATA as $key) {
     771            if (isset($metaData[$key])) {
    759772                $filteredMetaData[$key] = $metaData[$key];
    760773            }
     
    763776            $this->tableName,
    764777            [
    765                 'metaData' => maybe_serialize( $filteredMetaData ),
     778                'metaData' => maybe_serialize($filteredMetaData),
    766779            ],
    767780            [
     
    774787    }
    775788
    776     public function getBreadcrumbByKey( $key, $args = [] ) {
     789    public function getBreadcrumbByKey($key, $args = [])
     790    {
    777791        $defaults = [
    778792            'rootFileKey'   => null,
    779793            'rootFolderKey' => '/',
    780794        ];
    781         $args = wp_parse_args( $args, $defaults );
     795        $args = wp_parse_args($args, $defaults);
    782796        $rootFileKey = $args['rootFileKey'];
    783797        $rootFolderKey = $args['rootFolderKey'];
    784798        $home = [[
    785799            'fileKey' => '/',
    786             'name'    => __( 'Home', 'integrate-dropbox' ),
     800            'name'    => __('Home', 'integrate-dropbox'),
    787801        ]];
    788802        // Empty or root key
    789         if ( empty( $key ) || $key === '/' || $key === $rootFolderKey ) {
     803        if (empty($key) || $key === '/' || $key === $rootFolderKey) {
    790804            return $home;
    791805        }
    792806        // Resolve root folder key if rootFileKey is provided
    793         if ( $rootFileKey !== null && $rootFolderKey === '/' ) {
    794             $rootFile = $this->getFile( $rootFileKey, 'array' );
    795             if ( is_wp_error( $rootFile ) ) {
     807        if ($rootFileKey !== null && $rootFolderKey === '/') {
     808            $rootFile = $this->getFile($rootFileKey, 'array');
     809            if (is_wp_error($rootFile)) {
    796810                return $home;
    797811            }
    798812            $parentPath = $rootFile['parent'] ?? null;
    799             if ( $parentPath ) {
    800                 $rootFolder = $this->getFileByPath( $parentPath, $rootFile['accountId'] ?? '', 'array' );
    801                 if ( !is_wp_error( $rootFolder ) ) {
     813            if ($parentPath) {
     814                $rootFolder = $this->getFileByPath($parentPath, $rootFile['accountId'] ?? '', 'array');
     815                if (!is_wp_error($rootFolder)) {
    802816                    $rootFolderKey = $rootFolder['fileKey'] ?? '/';
    803817                }
    804818            }
    805819        }
    806         $file = $this->getFile( $key, 'array' );
    807         if ( is_wp_error( $file ) ) {
     820        $file = $this->getFile($key, 'array');
     821        if (is_wp_error($file)) {
    808822            return $home;
    809823        }
    810824        $fileId = $file['fileId'] ?? null;
    811825        $accountId = $file['accountId'] ?? null;
    812         if ( !$fileId || !$accountId ) {
     826        if (!$fileId || !$accountId) {
    813827            return $home;
    814828        }
     
    816830        $breadcrumb = [[
    817831            'fileKey' => $key,
    818             'name'    => $file['name'] ?? __( 'Unknown Folder', 'integrate-dropbox' ),
     832            'name'    => $file['name'] ?? __('Unknown Folder', 'integrate-dropbox'),
    819833        ]];
    820834        $parentPath = $file['parent'] ?? null;
    821835        // Stop if no parent
    822         if ( empty( $parentPath ) ) {
     836        if (empty($parentPath)) {
    823837            return $breadcrumb;
    824838        }
    825839        // Resolve parent folder key
    826840        $parentFolderKey = '/';
    827         if ( $parentPath !== '/' ) {
    828             $parentFolder = $this->getFileByPath( $parentPath, $accountId, 'array' );
    829             if ( is_wp_error( $parentFolder ) ) {
     841        if ($parentPath !== '/') {
     842            $parentFolder = $this->getFileByPath($parentPath, $accountId, 'array');
     843            if (is_wp_error($parentFolder)) {
    830844                return $home;
    831845            }
     
    833847        }
    834848        // Stop at root folder
    835         if ( $parentFolderKey === '/' || $parentFolderKey === $rootFolderKey ) {
    836             return array_merge( $breadcrumb, $home );
     849        if ($parentFolderKey === '/' || $parentFolderKey === $rootFolderKey) {
     850            return array_merge($breadcrumb, $home);
    837851        }
    838852        // Recursive parent breadcrumb
    839         $parentBreadcrumb = $this->getBreadcrumbByKey( $parentFolderKey, [
     853        $parentBreadcrumb = $this->getBreadcrumbByKey($parentFolderKey, [
    840854            'rootFolderKey' => $rootFolderKey,
    841         ] );
    842         if ( is_wp_error( $parentBreadcrumb ) ) {
     855        ]);
     856        if (is_wp_error($parentBreadcrumb)) {
    843857            return $parentBreadcrumb;
    844858        }
    845         return array_merge( $breadcrumb, $parentBreadcrumb );
    846     }
    847 
    848     public function getFileAttributesByKeys( array $keys, array $attributes = ['id'], $accountId = null ) {
    849         if ( empty( $keys ) ) {
     859        return array_merge($breadcrumb, $parentBreadcrumb);
     860    }
     861
     862    public function getFileAttributesByKeys(array $keys, array $attributes = ['id'], $accountId = null)
     863    {
     864        if (empty($keys)) {
    850865            return [];
    851866        }
    852867        global $wpdb;
    853         $placeholders = implode( ',', array_fill( 0, count( $keys ), '%s' ) );
    854         $preparedQuery = $wpdb->prepare( "SELECT * FROM %i WHERE `fileKey` IN ({$placeholders})", array_merge( [$this->tableName], $keys ) );
    855         if ( !empty( $accountId ) ) {
    856             $preparedQuery .= $wpdb->prepare( " AND `accountId` = %s", $accountId );
    857         }
    858         $cacheKey = "ccpidb_file_attributes_" . md5( $preparedQuery );
    859         if ( false !== ($cached = wp_cache_get( $cacheKey, 'ccpidb_files' )) ) {
     868        $placeholders = implode(',', array_fill(0, count($keys), '%s'));
     869        $preparedQuery = $wpdb->prepare("SELECT * FROM %i WHERE `fileKey` IN ({$placeholders})", array_merge([$this->tableName], $keys));
     870        if (!empty($accountId)) {
     871            $preparedQuery .= $wpdb->prepare(" AND `accountId` = %s", $accountId);
     872        }
     873        $cacheKey = "ccpidb_file_attributes_" . md5($preparedQuery);
     874        if (false !== ($cached = wp_cache_get($cacheKey, 'ccpidb_files'))) {
    860875            return $cached;
    861876        }
    862         $files = $wpdb->get_results( $preparedQuery );
    863         if ( empty( $files ) ) {
     877        $files = $wpdb->get_results($preparedQuery);
     878        if (empty($files)) {
    864879            return [];
    865880        }
    866         $processedFiles = $this->processFiles( $files, 'object' );
    867         if ( count( $attributes ) === 1 ) {
     881        $processedFiles = $this->processFiles($files, 'object');
     882        if (count($attributes) === 1) {
    868883            $attr = $attributes[0];
    869884            $result = [];
    870             foreach ( $processedFiles as $file ) {
     885            foreach ($processedFiles as $file) {
    871886                $result[] = $file->{$attr} ?? null;
    872887            }
    873             wp_cache_set( $cacheKey, $result, 'ccpidb_files' );
     888            wp_cache_set($cacheKey, $result, 'ccpidb_files');
    874889            return $result;
    875890        }
    876891        $result = [];
    877         foreach ( $processedFiles as $file ) {
     892        foreach ($processedFiles as $file) {
    878893            $fileData = [];
    879             foreach ( $attributes as $attr ) {
     894            foreach ($attributes as $attr) {
    880895                $fileData[$attr] = $file->{$attr} ?? null;
    881896            }
    882897            $result[] = $fileData;
    883898        }
    884         wp_cache_set( $cacheKey, $result, 'ccpidb_files' );
     899        wp_cache_set($cacheKey, $result, 'ccpidb_files');
    885900        return $result;
    886901    }
    887902
    888     public function getSuccessors( $parentPath, $accountId ) {
     903    public function getSuccessors($parentPath, $accountId)
     904    {
    889905        $successor = [];
    890         $folders = $this->getChildFolderIds( $parentPath, $accountId );
    891         foreach ( $folders as $folderRow ) {
     906        $folders = $this->getChildFolderIds($parentPath, $accountId);
     907        foreach ($folders as $folderRow) {
    892908            $folderPath = $folderRow['path'];
    893909            $successor[] = $folderPath;
    894             $childFolders = $this->getChildFolderIds( $folderPath, $accountId );
    895             if ( !empty( $childFolders ) ) {
    896                 $successor = array_merge( $successor, $this->getSuccessors( $folderPath, $accountId ) );
     910            $childFolders = $this->getChildFolderIds($folderPath, $accountId);
     911            if (!empty($childFolders)) {
     912                $successor = array_merge($successor, $this->getSuccessors($folderPath, $accountId));
    897913            }
    898914        }
    899915        $successor[] = $parentPath;
    900         return array_unique( $successor );
    901     }
    902 
    903     public function getAllPhotos( $args = [] ) {
     916        return array_unique($successor);
     917    }
     918
     919    public function getAllPhotos($args = [])
     920    {
    904921        $defaults = [
    905922            'perPage' => 40,
     
    908925            'order'   => 'desc',
    909926        ];
    910         $args = wp_parse_args( $args, $defaults );
     927        $args = wp_parse_args($args, $defaults);
    911928        $perPage = (int) $args['perPage'];
    912929        $page = (int) $args['page'];
    913         $orderBy = $this->sanitizeOrderBy( $args['orderBy'], [
     930        $orderBy = $this->sanitizeOrderBy($args['orderBy'], [
    914931            'name',
    915932            'createdAt',
    916933            'updatedAt',
    917934            'size'
    918         ] );
    919         $order = $this->sanitizeOrder( $args['order'] );
     935        ]);
     936        $order = $this->sanitizeOrder($args['order']);
    920937        $offset = ($page - 1) * $perPage;
    921938        global $wpdb;
    922939        $cache_key = "ccpidb_all_photos_{$perPage}_{$page}_{$orderBy}_{$order}";
    923         $photos = wp_cache_get( $cache_key, 'ccpidb_files' );
    924         if ( !empty( $photos ) ) {
     940        $photos = wp_cache_get($cache_key, 'ccpidb_files');
     941        if (!empty($photos)) {
    925942            return $photos;
    926943        }
    927         $photos = $wpdb->get_results( $wpdb->prepare(
     944        $photos = $wpdb->get_results($wpdb->prepare(
    928945            "SELECT * FROM %i WHERE mimeType LIKE %s ORDER BY %i {$order} LIMIT %d OFFSET %d",
    929946            $this->tableName,
     
    932949            $perPage,
    933950            $offset
    934         ) );
    935         if ( is_wp_error( $photos ) ) {
     951        ));
     952        if (is_wp_error($photos)) {
    936953            return $photos;
    937954        }
    938         $total = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE mimeType LIKE %s", $this->tableName, 'image/%' ) );
    939         if ( is_wp_error( $total ) ) {
     955        $total = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM %i WHERE mimeType LIKE %s", $this->tableName, 'image/%'));
     956        if (is_wp_error($total)) {
    940957            return $total;
    941958        }
    942         $totalPages = ceil( $total / $perPage );
     959        $totalPages = ceil($total / $perPage);
    943960        $hasMore = $page < $totalPages;
    944961        $response = [
     
    948965            'totalPages' => (int) $totalPages,
    949966            'hasMore'    => $hasMore,
    950             'photos'     => $this->processFiles( $photos ),
    951         ];
    952         if ( $hasMore ) {
     967            'photos'     => $this->processFiles($photos),
     968        ];
     969        if ($hasMore) {
    953970            $response['nextPage'] = $page + 1;
    954971        }
    955         if ( !empty( $photos ) ) {
    956             wp_cache_set( $cache_key, $response, 'ccpidb_files' );
     972        if (!empty($photos)) {
     973            wp_cache_set($cache_key, $response, 'ccpidb_files');
    957974        }
    958975        return $response;
    959976    }
    960977
    961     public function searchFiles( $query, $options = [] ) {
    962         global $wpdb;
    963         if ( empty( $query ) || empty( $options['accountId'] ) ) {
    964             return new WP_Error('invalid_query', __( 'Search query and account ID are required.', 'integrate-dropbox' ));
     978    public function searchFiles($query, $options = [])
     979    {
     980        global $wpdb;
     981        if (empty($query) || empty($options['accountId'])) {
     982            return new WP_Error('invalid_query', __('Search query and account ID are required.', 'integrate-dropbox'));
    965983        }
    966984        $defaults = [
     
    972990            'order'   => 'ASC',
    973991        ];
    974         $options = wp_parse_args( $options, $defaults );
    975         $order = $this->sanitizeOrder( $options['order'] );
    976         $orderBy = $this->sanitizeOrderBy( $options['orderBy'], [
     992        $options = wp_parse_args($options, $defaults);
     993        $order = $this->sanitizeOrder($options['order']);
     994        $orderBy = $this->sanitizeOrderBy($options['orderBy'], [
    977995            'name',
    978996            'createdAt',
    979997            'updatedAt',
    980998            'size'
    981         ] );
    982         $pagination = $this->sanitizePagination( $options['page'], $options['perPage'] );
     999        ]);
     1000        $pagination = $this->sanitizePagination($options['page'], $options['perPage']);
    9831001        $perPage = $pagination['perPage'];
    9841002        $offset = $pagination['offset'];
    9851003        $page = $pagination['page'];
    986         $searchPattern = '%' . $wpdb->esc_like( $query ) . '%';
     1004        $searchPattern = '%' . $wpdb->esc_like($query) . '%';
    9871005        $sql = $wpdb->prepare(
    9881006            "SELECT * FROM %i WHERE accountId = %s AND name LIKE %s",
     
    9971015            $searchPattern
    9981016        );
    999         if ( $options['scope'] === 'folder' && !empty( $options['path'] ) ) {
    1000             $sql .= $wpdb->prepare( " AND parent = %s", $options['path'] );
    1001             $totalSql .= $wpdb->prepare( " AND parent = %s", $options['path'] );
    1002         }
    1003         if ( !empty( $options['types'] ) && is_array( $options['types'] ) ) {
    1004             $extensions = MimeTypeManager::getExtensionsByCategory( $options['types'] );
    1005             if ( !empty( $extensions ) ) {
    1006                 $extPlaceholders = implode( ',', array_fill( 0, count( $extensions ), '%s' ) );
    1007                 $sql .= $wpdb->prepare( " AND extension IN ({$extPlaceholders})", $extensions );
    1008                 $totalSql .= $wpdb->prepare( " AND extension IN ({$extPlaceholders})", $extensions );
     1017        if ($options['scope'] === 'folder' && !empty($options['path'])) {
     1018            $sql .= $wpdb->prepare(" AND parent = %s", $options['path']);
     1019            $totalSql .= $wpdb->prepare(" AND parent = %s", $options['path']);
     1020        }
     1021        if (!empty($options['types']) && is_array($options['types'])) {
     1022            $extensions = MimeTypeManager::getExtensionsByCategory($options['types']);
     1023            if (!empty($extensions)) {
     1024                $extPlaceholders = implode(',', array_fill(0, count($extensions), '%s'));
     1025                $sql .= $wpdb->prepare(" AND extension IN ({$extPlaceholders})", $extensions);
     1026                $totalSql .= $wpdb->prepare(" AND extension IN ({$extPlaceholders})", $extensions);
    10091027            }
    10101028        }
     
    10151033            $offset
    10161034        );
    1017         $cache_key = "ccpidb_search_{$options['accountId']}_" . md5( $query . serialize( $options ) );
    1018         $cached = wp_cache_get( $cache_key, 'ccpidb_files' );
    1019         if ( !empty( $cached ) ) {
     1035        $cache_key = "ccpidb_search_{$options['accountId']}_" . md5($query . serialize($options));
     1036        $cached = wp_cache_get($cache_key, 'ccpidb_files');
     1037        if (!empty($cached)) {
    10201038            return $cached;
    10211039        }
    1022         $results = $wpdb->get_results( $sql );
    1023         $totalFile = $wpdb->get_var( $totalSql );
    1024         if ( is_wp_error( $results ) || is_wp_error( $totalFile ) ) {
     1040        $results = $wpdb->get_results($sql);
     1041        $totalFile = $wpdb->get_var($totalSql);
     1042        if (is_wp_error($results) || is_wp_error($totalFile)) {
    10251043            return $results;
    10261044        }
    1027         if ( empty( $results ) || $totalFile == 0 ) {
     1045        if (empty($results) || $totalFile == 0) {
    10281046            return [];
    10291047        }
    10301048        $response = [
    10311049            'total'       => (int) $totalFile,
    1032             'files'       => $this->processFiles( $results ),
     1050            'files'       => $this->processFiles($results),
    10331051            'perPage'     => $perPage,
    1034             'totalPages'  => ceil( $totalFile / $perPage ),
     1052            'totalPages'  => ceil($totalFile / $perPage),
    10351053            'currentPage' => $page,
    10361054            'hasMore'     => $page * $perPage < $totalFile,
    10371055        ];
    1038         if ( $response['hasMore'] ) {
     1056        if ($response['hasMore']) {
    10391057            $response['nextPage'] = $page + 1;
    10401058        }
    1041         if ( !empty( $results ) ) {
    1042             wp_cache_set( $cache_key, $response, 'ccpidb_files' );
     1059        if (!empty($results)) {
     1060            wp_cache_set($cache_key, $response, 'ccpidb_files');
    10431061        }
    10441062        return $response;
    10451063    }
    10461064
    1047     public function getSharedKey( $fileKey, $options = [] ) {
     1065    public function getSharedKey($fileKey, $options = [])
     1066    {
    10481067        $defaults = [
    10491068            'expireIn' => 3600,
    10501069            'password' => null,
    10511070        ];
    1052         $options = wp_parse_args( $options, $defaults );
    1053         $expireIn = intval( $options['expireIn'] );
    1054         $password = sanitize_text_field( $options['password'] ?? null );
    1055         $expiry = ( $expireIn > 0 ? time() + $expireIn : 0 );
    1056         $passwordHash = ( !empty( $password ) ? md5( $password ) : '' );
    1057         $sharedData = $this->getSharedData( $fileKey );
    1058         $key = md5( "{$fileKey}|{$expiry}|{$passwordHash}" );
    1059         if ( !empty( $sharedData[$key] ) && $sharedData[$key]['expiry'] >= time() ) {
     1071        $options = wp_parse_args($options, $defaults);
     1072        $expireIn = intval($options['expireIn']);
     1073        $password = sanitize_text_field($options['password'] ?? null);
     1074        $expiry = ($expireIn > 0 ? time() + $expireIn : 0);
     1075        $passwordHash = (!empty($password) ? md5($password) : '');
     1076        $sharedData = $this->getSharedData($fileKey);
     1077        $key = md5("{$fileKey}|{$expiry}|{$passwordHash}");
     1078        if (!empty($sharedData[$key]) && $sharedData[$key]['expiry'] >= time()) {
    10601079            return "{$fileKey}-{$key}";
    10611080        }
     
    10671086        ];
    10681087        // Save entire sharedData list
    1069         $this->saveSharedData( $fileKey, $sharedData );
     1088        $this->saveSharedData($fileKey, $sharedData);
    10701089        return "{$fileKey}-{$key}";
    10711090    }
    10721091
    1073     public function getDownloadKey( $fileKey, $options = [] ) {
     1092    public function getDownloadKey($fileKey, $options = [])
     1093    {
    10741094        $defaults = [
    10751095            'expireIn' => 3600,
     
    10771097            'limit'    => 0,
    10781098        ];
    1079         $options = wp_parse_args( $options, $defaults );
    1080         $expireIn = intval( $options['expireIn'] );
    1081         $password = sanitize_text_field( $options['password'] ?? null );
    1082         $limit = intval( $options['limit'] );
    1083         $expiry = ( $expireIn > 0 ? time() + $expireIn : 0 );
    1084         $passwordHash = ( !empty( $password ) ? md5( $password ) : '' );
    1085         $downloadData = $this->getDownloadData( $fileKey );
    1086         $key = md5( "{$fileKey}|{$expiry}|{$passwordHash}|{$limit}" );
    1087         if ( !empty( $downloadData[$key] ) && $downloadData[$key]['expiry'] >= time() ) {
     1099        $options = wp_parse_args($options, $defaults);
     1100        $expireIn = intval($options['expireIn']);
     1101        $password = sanitize_text_field($options['password'] ?? null);
     1102        $limit = intval($options['limit']);
     1103        $expiry = ($expireIn > 0 ? time() + $expireIn : 0);
     1104        $passwordHash = (!empty($password) ? md5($password) : '');
     1105        $downloadData = $this->getDownloadData($fileKey);
     1106        $key = md5("{$fileKey}|{$expiry}|{$passwordHash}|{$limit}");
     1107        if (!empty($downloadData[$key]) && $downloadData[$key]['expiry'] >= time()) {
    10881108            return "{$fileKey}-{$key}";
    10891109        }
     
    10961116        ];
    10971117        // Save entire sharedData list
    1098         $this->saveDownloadData( $fileKey, $downloadData );
     1118        $this->saveDownloadData($fileKey, $downloadData);
    10991119        return "{$fileKey}-{$key}";
    11001120    }
    11011121
    1102     public function validateSharedLink( $combinedKey, $password = '' ) {
    1103         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1104         if ( !$fileKey || !$linkKey ) {
    1105             return false;
    1106         }
    1107         $sharedData = $this->getSharedData( $fileKey );
    1108         if ( empty( $sharedData[$linkKey] ) ) {
     1122    public function validateSharedLink($combinedKey, $password = '')
     1123    {
     1124        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1125        if (!$fileKey || !$linkKey) {
     1126            return false;
     1127        }
     1128        $sharedData = $this->getSharedData($fileKey);
     1129        if (empty($sharedData[$linkKey])) {
    11091130            return false;
    11101131        }
    11111132        $shareInfo = $sharedData[$linkKey];
    1112         if ( $shareInfo['expiry'] < time() && $shareInfo['expiry'] != 0 ) {
    1113             $this->deleteSharedEntry( $fileKey, $linkKey );
    1114             return false;
    1115         }
    1116         $hashedPassword = md5( sanitize_text_field( $password ) );
    1117         if ( !empty( $shareInfo['password'] ) ) {
    1118             if ( empty( $password ) ) {
    1119                 return new WP_Error('password_required', __( 'This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox' ));
    1120             }
    1121             if ( $shareInfo['password'] !== $hashedPassword ) {
    1122                 return new WP_Error('invalid_password', __( 'The provided password is incorrect.', 'integrate-dropbox' ));
    1123             }
    1124         }
    1125         $shareInfo['viewCount'] = intval( $shareInfo['viewCount'] ?? 0 ) + 1;
    1126         $shareInfo['lastViewed'] = current_time( 'mysql' );
    1127         $result = $this->updateSharedData( $combinedKey, $shareInfo );
    1128         if ( is_wp_error( $result ) ) {
     1133        if ($shareInfo['expiry'] < time() && $shareInfo['expiry'] != 0) {
     1134            $this->deleteSharedEntry($fileKey, $linkKey);
     1135            return false;
     1136        }
     1137        $hashedPassword = md5(sanitize_text_field($password));
     1138        if (!empty($shareInfo['password'])) {
     1139            if (empty($password)) {
     1140                return new WP_Error('password_required', __('This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox'));
     1141            }
     1142            if ($shareInfo['password'] !== $hashedPassword) {
     1143                return new WP_Error('invalid_password', __('The provided password is incorrect.', 'integrate-dropbox'));
     1144            }
     1145        }
     1146        $shareInfo['viewCount'] = intval($shareInfo['viewCount'] ?? 0) + 1;
     1147        $shareInfo['lastViewed'] = current_time('mysql');
     1148        $result = $this->updateSharedData($combinedKey, $shareInfo);
     1149        if (is_wp_error($result)) {
    11291150            return false;
    11301151        }
     
    11321153    }
    11331154
    1134     public function validateDownloadLink( $combinedKey, $password = '' ) {
    1135         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1136         if ( !$fileKey || !$linkKey ) {
    1137             return false;
    1138         }
    1139         $downloadData = $this->getDownloadData( $fileKey );
    1140         if ( empty( $downloadData[$linkKey] ) ) {
     1155    public function validateDownloadLink($combinedKey, $password = '')
     1156    {
     1157        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1158        if (!$fileKey || !$linkKey) {
     1159            return false;
     1160        }
     1161        $downloadData = $this->getDownloadData($fileKey);
     1162        if (empty($downloadData[$linkKey])) {
    11411163            return false;
    11421164        }
    11431165        $downloadInfo = $downloadData[$linkKey];
    1144         if ( $downloadInfo['expiry'] < time() && $downloadInfo['expiry'] != 0 ) {
    1145             $this->deleteDownloadEntry( $fileKey, $linkKey );
    1146             return false;
    1147         }
    1148         $downloadLimit = intval( $downloadInfo['limit'] ?? 0 );
    1149         if ( $downloadLimit > 0 && intval( $downloadInfo['downloadCount'] ?? 0 ) >= $downloadLimit ) {
    1150             $this->deleteDownloadEntry( $fileKey, $linkKey );
    1151             return new WP_Error('download_limit_exceeded', __( 'The download limit for this link has been exceeded.', 'integrate-dropbox' ));
    1152         }
    1153         $hashedPassword = md5( sanitize_text_field( $password ) );
    1154         if ( !empty( $downloadInfo['password'] ) ) {
    1155             if ( empty( $password ) ) {
    1156                 return new WP_Error('password_required', __( 'This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox' ));
    1157             }
    1158             if ( $downloadInfo['password'] !== $hashedPassword ) {
    1159                 return new WP_Error('invalid_password', __( 'The provided password is incorrect.', 'integrate-dropbox' ));
    1160             }
    1161         }
    1162         $downloadInfo['downloadCount'] = intval( $downloadInfo['downloadCount'] ?? 0 ) + 1;
    1163         $downloadInfo['lastViewed'] = current_time( 'mysql' );
    1164         $result = $this->updateDownloadData( $combinedKey, $downloadInfo );
    1165         if ( is_wp_error( $result ) ) {
     1166        if ($downloadInfo['expiry'] < time() && $downloadInfo['expiry'] != 0) {
     1167            $this->deleteDownloadEntry($fileKey, $linkKey);
     1168            return false;
     1169        }
     1170        $downloadLimit = intval($downloadInfo['limit'] ?? 0);
     1171        if ($downloadLimit > 0 && intval($downloadInfo['downloadCount'] ?? 0) >= $downloadLimit) {
     1172            $this->deleteDownloadEntry($fileKey, $linkKey);
     1173            return new WP_Error('download_limit_exceeded', __('The download limit for this link has been exceeded.', 'integrate-dropbox'));
     1174        }
     1175        $hashedPassword = md5(sanitize_text_field($password));
     1176        if (!empty($downloadInfo['password'])) {
     1177            if (empty($password)) {
     1178                return new WP_Error('password_required', __('This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox'));
     1179            }
     1180            if ($downloadInfo['password'] !== $hashedPassword) {
     1181                return new WP_Error('invalid_password', __('The provided password is incorrect.', 'integrate-dropbox'));
     1182            }
     1183        }
     1184        $downloadInfo['downloadCount'] = intval($downloadInfo['downloadCount'] ?? 0) + 1;
     1185        $downloadInfo['lastViewed'] = current_time('mysql');
     1186        $result = $this->updateDownloadData($combinedKey, $downloadInfo);
     1187        if (is_wp_error($result)) {
    11661188            return false;
    11671189        }
     
    11701192
    11711193    /* ================= PRIVATE ================= */
    1172     private function parseCombinedKey( $sharedKey ) {
    1173         $parts = explode( '-', $sharedKey, 2 );
     1194    private function parseCombinedKey($sharedKey)
     1195    {
     1196        $parts = explode('-', $sharedKey, 2);
    11741197        return [$parts[0] ?? '', $parts[1] ?? ''];
    11751198    }
    11761199
    1177     private function getSharedData( $fileKey ) {
    1178         global $wpdb;
    1179         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1180         if ( !$file ) {
     1200    private function getSharedData($fileKey)
     1201    {
     1202        global $wpdb;
     1203        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1204        if (!$file) {
    11811205            return [];
    11821206        }
    1183         $metaData = maybe_unserialize( $file->metaData );
     1207        $metaData = maybe_unserialize($file->metaData);
    11841208        return $metaData['sharedData'] ?? [];
    11851209    }
    11861210
    1187     private function getDownloadData( $fileKey ) {
    1188         global $wpdb;
    1189         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1190         if ( !$file ) {
     1211    private function getDownloadData($fileKey)
     1212    {
     1213        global $wpdb;
     1214        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1215        if (!$file) {
    11911216            return [];
    11921217        }
    1193         $metaData = maybe_unserialize( $file->metaData );
     1218        $metaData = maybe_unserialize($file->metaData);
    11941219        return $metaData['downloadData'] ?? [];
    11951220    }
    11961221
    1197     private function saveSharedData( $fileKey, $sharedData ) {
    1198         global $wpdb;
    1199         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1200         if ( !$file ) {
    1201             return false;
    1202         }
    1203         $metaData = maybe_unserialize( $file->metaData ) ?? [];
     1222    private function saveSharedData($fileKey, $sharedData)
     1223    {
     1224        global $wpdb;
     1225        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1226        if (!$file) {
     1227            return false;
     1228        }
     1229        $metaData = maybe_unserialize($file->metaData) ?? [];
    12041230        $metaData['sharedData'] = $sharedData;
    12051231        return $wpdb->update(
    12061232            $this->tableName,
    12071233            [
    1208                 'metaData' => maybe_serialize( $metaData ),
     1234                'metaData' => maybe_serialize($metaData),
    12091235            ],
    12101236            [
     
    12161242    }
    12171243
    1218     private function saveDownloadData( $fileKey, $downloadData ) {
    1219         global $wpdb;
    1220         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1221         if ( !$file ) {
    1222             return false;
    1223         }
    1224         $metaData = maybe_unserialize( $file->metaData ) ?? [];
     1244    private function saveDownloadData($fileKey, $downloadData)
     1245    {
     1246        global $wpdb;
     1247        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1248        if (!$file) {
     1249            return false;
     1250        }
     1251        $metaData = maybe_unserialize($file->metaData) ?? [];
    12251252        $metaData['downloadData'] = $downloadData;
    12261253        return $wpdb->update(
    12271254            $this->tableName,
    12281255            [
    1229                 'metaData' => maybe_serialize( $metaData ),
     1256                'metaData' => maybe_serialize($metaData),
    12301257            ],
    12311258            [
     
    12371264    }
    12381265
    1239     public function updateSharedData( $combinedKey, $updates = [] ) {
    1240         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1241         if ( !$fileKey || !$linkKey ) {
    1242             return false;
    1243         }
    1244         $sharedData = $this->getSharedData( $fileKey );
    1245         if ( empty( $sharedData[$linkKey] ) ) {
     1266    public function updateSharedData($combinedKey, $updates = [])
     1267    {
     1268        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1269        if (!$fileKey || !$linkKey) {
     1270            return false;
     1271        }
     1272        $sharedData = $this->getSharedData($fileKey);
     1273        if (empty($sharedData[$linkKey])) {
    12461274            return false;
    12471275        }
    12481276        // Only update provided fields
    1249         $sharedData[$linkKey] = array_merge( $sharedData[$linkKey], array_filter( $updates, function ( $v ) {
     1277        $sharedData[$linkKey] = array_merge($sharedData[$linkKey], array_filter($updates, function ($v) {
    12501278            return $v !== null;
    1251         } ) );
    1252         return $this->saveSharedData( $fileKey, $sharedData );
    1253     }
    1254 
    1255     public function updateDownloadData( $combinedKey, $updates = [] ) {
    1256         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1257         if ( !$fileKey || !$linkKey ) {
    1258             return false;
    1259         }
    1260         $downloadData = $this->getDownloadData( $fileKey );
    1261         if ( empty( $downloadData[$linkKey] ) ) {
     1279        }));
     1280        return $this->saveSharedData($fileKey, $sharedData);
     1281    }
     1282
     1283    public function updateDownloadData($combinedKey, $updates = [])
     1284    {
     1285        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1286        if (!$fileKey || !$linkKey) {
     1287            return false;
     1288        }
     1289        $downloadData = $this->getDownloadData($fileKey);
     1290        if (empty($downloadData[$linkKey])) {
    12621291            return false;
    12631292        }
    12641293        // Only update provided fields
    1265         $downloadData[$linkKey] = array_merge( $downloadData[$linkKey], array_filter( $updates, function ( $v ) {
     1294        $downloadData[$linkKey] = array_merge($downloadData[$linkKey], array_filter($updates, function ($v) {
    12661295            return $v !== null;
    1267         } ) );
    1268         return $this->saveDownloadData( $fileKey, $downloadData );
    1269     }
    1270 
    1271     private function deleteSharedEntry( $fileKey, $linkKey ) {
    1272         $sharedData = $this->getSharedData( $fileKey );
    1273         if ( isset( $sharedData[$linkKey] ) ) {
     1296        }));
     1297        return $this->saveDownloadData($fileKey, $downloadData);
     1298    }
     1299
     1300    private function deleteSharedEntry($fileKey, $linkKey)
     1301    {
     1302        $sharedData = $this->getSharedData($fileKey);
     1303        if (isset($sharedData[$linkKey])) {
    12741304            unset($sharedData[$linkKey]);
    1275             return $this->saveSharedData( $fileKey, $sharedData );
     1305            return $this->saveSharedData($fileKey, $sharedData);
    12761306        }
    12771307        return false;
    12781308    }
    12791309
    1280     private function deleteDownloadEntry( $fileKey, $linkKey ) {
    1281         $downloadData = $this->getDownloadData( $fileKey );
    1282         if ( isset( $downloadData[$linkKey] ) ) {
     1310    private function deleteDownloadEntry($fileKey, $linkKey)
     1311    {
     1312        $downloadData = $this->getDownloadData($fileKey);
     1313        if (isset($downloadData[$linkKey])) {
    12831314            unset($downloadData[$linkKey]);
    1284             return $this->saveDownloadData( $fileKey, $downloadData );
     1315            return $this->saveDownloadData($fileKey, $downloadData);
    12851316        }
    12861317        return false;
    12871318    }
    12881319
    1289     private function getChildFolderIds( $parentPath, $accountId ) {
    1290         if ( empty( $parentPath ) || empty( $accountId ) ) {
     1320    private function getChildFolderIds($parentPath, $accountId)
     1321    {
     1322        if (empty($parentPath) || empty($accountId)) {
    12911323            return [];
    12921324        }
    12931325        global $wpdb;
    1294         return $wpdb->get_results( $wpdb->prepare(
     1326        return $wpdb->get_results($wpdb->prepare(
    12951327            "SELECT path FROM %i WHERE parent = %s AND accountId = %s AND extension = 'folder'",
    12961328            $this->tableName,
    12971329            $parentPath,
    12981330            $accountId
    1299         ), ARRAY_A );
    1300     }
    1301 
    1302     private function processFiles( $files, $returnType = 'array', $filter = null ) {
     1331        ), ARRAY_A);
     1332    }
     1333
     1334    private function processFiles($files, $returnType = 'array', $filter = null)
     1335    {
    13031336        $processedFiles = [];
    1304         foreach ( $files as $file ) {
    1305             $processedFiles[] = $this->processFile( $file, $returnType, $filter );
     1337        foreach ($files as $file) {
     1338            $processedFiles[] = $this->processFile($file, $returnType, $filter);
    13061339        }
    13071340        return $processedFiles;
    13081341    }
    13091342
    1310     private function processFile( $file, $returnType = 'object', $filter = null ) {
    1311         if ( empty( $file ) ) {
     1343    private function processFile($file, $returnType = 'object', $filter = null)
     1344    {
     1345        if (empty($file)) {
    13121346            return [];
    13131347        }
     
    13271361            'sharedLink'      => $file->sharedLink,
    13281362            'isDir'           => $file->isDir,
    1329             'permissions'     => maybe_unserialize( $file->permissions ),
     1363            'permissions'     => maybe_unserialize($file->permissions),
    13301364            'hasOwnThumbnail' => $file->hasOwnThumbnail,
    13311365            'icon'            => $file->icon,
    1332             'additionalData'  => maybe_unserialize( $file->additionalData ),
    1333             'metaData'        => maybe_unserialize( $file->metaData ),
     1366            'additionalData'  => maybe_unserialize($file->additionalData),
     1367            'metaData'        => maybe_unserialize($file->metaData),
    13341368            'createdAt'       => $file->createdAt,
    13351369            'updatedAt'       => $file->updatedAt,
    13361370        ];
    1337         if ( $returnType === 'object' ) {
     1371        if ($returnType === 'object') {
    13381372            return new File($fileData);
    1339         } elseif ( $returnType === 'array' ) {
     1373        } elseif ($returnType === 'array') {
    13401374            return $fileData;
    13411375        }
     
    13461380            'mimeType'   => $file->mimeType,
    13471381            'size'       => $file->size,
    1348             'thumbnails' => maybe_unserialize( $file->thumbnails ),
    1349         ];
    1350     }
    1351 
    1352     private function processExtensions( array $extensions, array $additionalExtensions, string $filterType ) : array {
    1353         if ( empty( $additionalExtensions ) ) {
     1382            'thumbnails' => maybe_unserialize($file->thumbnails),
     1383        ];
     1384    }
     1385
     1386    private function processExtensions(array $extensions, array $additionalExtensions, string $filterType): array
     1387    {
     1388        if (empty($additionalExtensions)) {
    13541389            return $extensions;
    13551390        }
    1356         if ( empty( $extensions ) ) {
     1391        if (empty($extensions)) {
    13571392            return $additionalExtensions;
    13581393        }
    1359         if ( $filterType === 'include' ) {
    1360             $filterExtensions = array_filter( $extensions, function ( $ext ) use($additionalExtensions) {
    1361                 return in_array( $ext, $additionalExtensions );
    1362             } );
    1363             return array_values( $filterExtensions );
    1364         } elseif ( $filterType === 'exclude' ) {
    1365             $filterExtensions = array_filter( $extensions, fn( $ext ) => !in_array( $ext, $additionalExtensions ) );
    1366             return array_values( $filterExtensions );
     1394        if ($filterType === 'include') {
     1395            $filterExtensions = array_filter($extensions, function ($ext) use ($additionalExtensions) {
     1396                return in_array($ext, $additionalExtensions);
     1397            });
     1398            return array_values($filterExtensions);
     1399        } elseif ($filterType === 'exclude') {
     1400            $filterExtensions = array_filter($extensions, fn ($ext) => !in_array($ext, $additionalExtensions));
     1401            return array_values($filterExtensions);
    13671402        }
    13681403        return $extensions;
    13691404    }
    13701405
    1371     private function processFolderTree( array $items, array $rootPaths ) {
     1406    private function processFolderTree(array $items, array $rootPaths)
     1407    {
    13721408        $tree = [];
    13731409        $lookup = [];
    1374         foreach ( $items as $item ) {
    1375             $path = rtrim( $item['path'], '/' );
     1410        foreach ($items as $item) {
     1411            $path = rtrim($item['path'], '/');
    13761412            $lookup[$path] = [
    13771413                'name'     => $item['name'],
     
    13791415                'children' => [],
    13801416                'path'     => $path,
    1381                 'parent'   => rtrim( $item['parent'], '/' ),
     1417                'parent'   => rtrim($item['parent'], '/'),
    13821418            ];
    13831419        }
    1384         foreach ( $lookup as $path => &$node ) {
    1385             if ( in_array( $node['path'], $rootPaths, true ) || $node['parent'] === '' || $node['parent'] === '/' ) {
     1420        foreach ($lookup as $path => &$node) {
     1421            if (in_array($node['path'], $rootPaths, true) || $node['parent'] === '' || $node['parent'] === '/') {
    13861422                unset($node['parent']);
    1387                 $tree[] =& $node;
     1423                $tree[] = & $node;
    13881424            } else {
    1389                 if ( isset( $lookup[$node['parent']] ) ) {
    1390                     $lookup[$node['parent']]['children'][] =& $node;
     1425                if (isset($lookup[$node['parent']])) {
     1426                    $lookup[$node['parent']]['children'][] = & $node;
    13911427                }
    13921428            }
     
    14021438        //     }
    14031439        // }
    1404         $tree = array_map( function ( $item ) {
    1405             if ( empty( $item['children'] ) ) {
     1440        $tree = array_map(function ($item) {
     1441            if (empty($item['children'])) {
    14061442                unset($item['children']);
    14071443            }
    14081444            return $item;
    1409         }, $tree );
    1410         return array_values( $tree );
     1445        }, $tree);
     1446        return array_values($tree);
    14111447    }
    14121448
  • integrate-dropbox/trunk/models/Files.php

    r3448719 r3448768  
    99use CodeConfig\IDB\Utils\MimeTypeManager;
    1010use CodeConfig\IDB\Utils\Singleton;
     11use WP_Error;
     12
    1113use function count;
    1214use function in_array;
    1315use function intval;
    1416use function is_array;
    15 use WP_Error;
    16 class Files extends BaseModel {
     17
     18class Files extends BaseModel
     19{
    1720    use Singleton;
    1821    public const TABLE_NAME = 'ccpidb_files';
     
    5659    public const META_DATA = ['attachmentId', 'mediaInfo', 'childCount'];
    5760
    58     public function __construct() {
    59         parent::__construct( self::TABLE_NAME );
     61    public function __construct()
     62    {
     63        parent::__construct(self::TABLE_NAME);
    6064        // $this->getChildPathsWithThumbnails(['7618d90767fefcb7d21109071e707ae1'], 'id:XR5DPLkvVHQAAAAAAAADAA');
    6165        // $this->getChildPathsWithThumbnails(['7618d90767fefcb7d21109071e707ae1'], 'id:XR5DPLkvVHQAAAAAAAADAA');
     
    7175     * @return array|null|WP_Error An array of processed file data from the specified folder.
    7276     */
    73     public function getFolder( $folderKey, $config = [] ) {
     77    public function getFolder($folderKey, $config = [])
     78    {
    7479        global $wpdb;
    7580        $allowedOrderBy = [
     
    7984            'size'
    8085        ];
    81         $order = $this->sanitizeOrder( $config['order'] ?? 'DESC' );
    82         $orderBy = $this->sanitizeOrderBy( $config['orderBy'] ?? 'createdAt', $allowedOrderBy );
    83         $page = ( isset( $config['page'] ) ? (int) $config['page'] : 1 );
    84         $perPage = ( isset( $config['perPage'] ) ? (int) $config['perPage'] : 20 );
    85         $pagination = $this->sanitizePagination( $page, $perPage );
    86         if ( $folderKey !== '/' ) {
    87             $file = $this->getFile( $folderKey );
    88             if ( $file instanceof File === false || is_wp_error( $file ) ) {
    89                 return new WP_Error(404, __( 'Folder not found.', 'integrate-dropbox' ));
     86        $order = $this->sanitizeOrder($config['order'] ?? 'DESC');
     87        $orderBy = $this->sanitizeOrderBy($config['orderBy'] ?? 'createdAt', $allowedOrderBy);
     88        $page = (isset($config['page']) ? (int) $config['page'] : 1);
     89        $perPage = (isset($config['perPage']) ? (int) $config['perPage'] : 20);
     90        $pagination = $this->sanitizePagination($page, $perPage);
     91        if ($folderKey !== '/') {
     92            $file = $this->getFile($folderKey);
     93            if ($file instanceof File === false || is_wp_error($file)) {
     94                return new WP_Error(404, __('Folder not found.', 'integrate-dropbox'));
    9095            }
    9196            $accountId = $file->getAccountId();
     
    9398        } else {
    9499            $account = Accounts::getInstance()->getAccount();
    95             if ( $account instanceof Account === false || is_wp_error( $account ) ) {
    96                 return new WP_Error(404, __( 'Account not found.', 'integrate-dropbox' ));
     100            if ($account instanceof Account === false || is_wp_error($account)) {
     101                return new WP_Error(404, __('Account not found.', 'integrate-dropbox'));
    97102            }
    98103            $accountId = $account->getId();
    99104            $path = '/';
    100105        }
    101         if ( !current_user_can( 'manage_options' ) && !wp_doing_cron() ) {
    102             if ( !is_user_logged_in() ) {
    103                 return new WP_Error('unauthorized', __( 'You must be logged in to access this folder.', 'integrate-dropbox' ));
     106        if (!current_user_can('manage_options') && !wp_doing_cron()) {
     107            if (!is_user_logged_in()) {
     108                return new WP_Error('unauthorized', __('You must be logged in to access this folder.', 'integrate-dropbox'));
    104109            }
    105110            $user = wp_get_current_user();
    106             if ( !$user instanceof \WP_User ) {
    107                 return new WP_Error('unauthorized', __( 'You must be logged in to access this folder.', 'integrate-dropbox' ));
     111            if (!$user instanceof \WP_User) {
     112                return new WP_Error('unauthorized', __('You must be logged in to access this folder.', 'integrate-dropbox'));
    108113            }
    109114            $userName = $user->user_login;
    110115            $roles = $user->roles;
    111             $accessSettings = UserAccess::getInstance()->getAccessData( $userName, $roles );
    112             if ( empty( $accessSettings ) ) {
    113                 if ( !current_user_can( 'manage_options' ) ) {
    114                     return new WP_Error('forbidden', __( 'You do not have permission to access this folder.', 'integrate-dropbox' ));
     116            $accessSettings = UserAccess::getInstance()->getAccessData($userName, $roles);
     117            if (empty($accessSettings)) {
     118                if (!current_user_can('manage_options')) {
     119                    return new WP_Error('forbidden', __('You do not have permission to access this folder.', 'integrate-dropbox'));
    115120                }
    116121            } else {
    117122                $accessSettingsFolders = $accessSettings['folders'] ?? [];
    118                 if ( empty( $accessSettingsFolders ) || !is_array( $accessSettingsFolders ) ) {
    119                     return new WP_Error('forbidden', __( 'You do not have permission to access this folder.', 'integrate-dropbox' ));
     123                if (empty($accessSettingsFolders) || !is_array($accessSettingsFolders)) {
     124                    return new WP_Error('forbidden', __('You do not have permission to access this folder.', 'integrate-dropbox'));
    120125                }
    121                 if ( $folderKey === '/' ) {
    122                     $folder = $this->getFilesByKeys( $accessSettingsFolders, [
     126                if ($folderKey === '/') {
     127                    $folder = $this->getFilesByKeys($accessSettingsFolders, [
    123128                        'returnType' => 'array',
    124129                        'perPage'    => $config['perPage'],
     
    127132                        'order'      => $config['order'],
    128133                        'recursive'  => false,
    129                     ] );
     134                    ]);
    130135                    return $folder;
    131136                }
    132                 if ( !Helpers::validateFileKey( $folderKey, $accessSettingsFolders ) ) {
    133                     return new WP_Error('forbidden', __( 'You do not have permission to access this folder.', 'integrate-dropbox' ));
     137                if (!Helpers::validateFileKey($folderKey, $accessSettingsFolders)) {
     138                    return new WP_Error('forbidden', __('You do not have permission to access this folder.', 'integrate-dropbox'));
    134139                }
    135140            }
    136141        }
    137         $sql = $wpdb->prepare( "SELECT * FROM %i WHERE accountId = %s", $this->tableName, $accountId );
    138         $totalSql = $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE accountId = %s", $this->tableName, $accountId );
    139         if ( !empty( $config['search'] ) ) {
    140             $searchPattern = '%' . $wpdb->esc_like( $config['search'] ?? '' ) . '%';
    141             $searchScope = ( in_array( $config['searchScope'] ?? 'folder', ['folder', 'global'] ) ? $config['searchScope'] : 'folder' );
    142             $sql .= $wpdb->prepare( " AND name LIKE %s", $searchPattern );
    143             $totalSql .= $wpdb->prepare( " AND name LIKE %s", $searchPattern );
    144             if ( $searchScope === 'folder' ) {
    145                 $sql .= $wpdb->prepare( " AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%" );
    146                 $totalSql .= $wpdb->prepare( " AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%" );
     142        $sql = $wpdb->prepare("SELECT * FROM %i WHERE accountId = %s", $this->tableName, $accountId);
     143        $totalSql = $wpdb->prepare("SELECT COUNT(*) FROM %i WHERE accountId = %s", $this->tableName, $accountId);
     144        if (!empty($config['search'])) {
     145            $searchPattern = '%' . $wpdb->esc_like($config['search'] ?? '') . '%';
     146            $searchScope = (in_array($config['searchScope'] ?? 'folder', ['folder', 'global']) ? $config['searchScope'] : 'folder');
     147            $sql .= $wpdb->prepare(" AND name LIKE %s", $searchPattern);
     148            $totalSql .= $wpdb->prepare(" AND name LIKE %s", $searchPattern);
     149            if ($searchScope === 'folder') {
     150                $sql .= $wpdb->prepare(" AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%");
     151                $totalSql .= $wpdb->prepare(" AND (path LIKE %s OR parent LIKE %s)", "{$path}%", "{$path}%");
    147152            }
    148153        } else {
    149             if ( !empty( $config['recursive'] ) && $config['recursive'] === true ) {
    150                 $sql .= $wpdb->prepare( " AND parent LIKE %s", "{$path}%" );
    151                 $totalSql .= $wpdb->prepare( " AND parent LIKE %s", "{$path}%" );
     154            if (!empty($config['recursive']) && $config['recursive'] === true) {
     155                $sql .= $wpdb->prepare(" AND parent LIKE %s", "{$path}%");
     156                $totalSql .= $wpdb->prepare(" AND parent LIKE %s", "{$path}%");
    152157            } else {
    153                 $sql .= $wpdb->prepare( " AND parent = %s", $path );
    154                 $totalSql .= $wpdb->prepare( " AND parent = %s", $path );
    155             }
    156         }
    157         if ( !empty( $config['types'] ) && is_array( $config['types'] ) ) {
     158                $sql .= $wpdb->prepare(" AND parent = %s", $path);
     159                $totalSql .= $wpdb->prepare(" AND parent = %s", $path);
     160            }
     161        }
     162        if (!empty($config['types']) && is_array($config['types'])) {
    158163            $types = $config['types'];
    159             $extensions = MimeTypeManager::getExtensionsByCategory( $types );
    160             $placeholders = implode( ',', array_fill( 0, count( $extensions ), '%s' ) );
    161             $sql .= $wpdb->prepare( " AND `extension` IN ({$placeholders})", $extensions );
    162             $totalSql .= $wpdb->prepare( " AND `extension` IN ({$placeholders})", $extensions );
     164            $extensions = MimeTypeManager::getExtensionsByCategory($types);
     165            $placeholders = implode(',', array_fill(0, count($extensions), '%s'));
     166            $sql .= $wpdb->prepare(" AND `extension` IN ({$placeholders})", $extensions);
     167            $totalSql .= $wpdb->prepare(" AND `extension` IN ({$placeholders})", $extensions);
    163168        }
    164169        $sql .= $wpdb->prepare(
     
    168173            $pagination['offset']
    169174        );
    170         $cache_key = "ccpidb_folder_" . md5( $sql );
    171         $cache_group = "ccpidb_files_" . md5( "{$path}_{$accountId}" );
    172         $files = wp_cache_get( $cache_key, $cache_group );
    173         if ( $files !== false ) {
     175        $cache_key = "ccpidb_folder_" . md5($sql);
     176        $cache_group = "ccpidb_files_" . md5("{$path}_{$accountId}");
     177        $files = wp_cache_get($cache_key, $cache_group);
     178        if ($files !== false) {
    174179            return $files;
    175180        }
    176181        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    177         $files = $wpdb->get_results( $sql );
     182        $files = $wpdb->get_results($sql);
    178183        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    179         $total = $wpdb->get_var( $totalSql );
    180         if ( empty( $files ) || is_wp_error( $files ) ) {
     184        $total = $wpdb->get_var($totalSql);
     185        if (empty($files) || is_wp_error($files)) {
    181186            $files = [];
    182187        }
    183         $processedFiles = $this->processFiles( $files );
    184         $totalPages = ceil( $total / $perPage );
     188        $processedFiles = $this->processFiles($files);
     189        $totalPages = ceil($total / $perPage);
    185190        $hasMore = $totalPages > $page;
    186191        $response = [
    187             'breadcrumb'  => array_reverse( $this->getBreadcrumbByKey( $folderKey ) ),
    188             'totalPage'   => ( $totalPages < 1 ? 1 : $totalPages ),
     192            'breadcrumb'  => array_reverse($this->getBreadcrumbByKey($folderKey)),
     193            'totalPage'   => ($totalPages < 1 ? 1 : $totalPages),
    189194            'hasMore'     => $hasMore,
    190195            'currentPage' => $page,
    191196            'files'       => $processedFiles,
    192             'totalFiles'  => intval( $total ),
    193         ];
    194         if ( $hasMore ) {
     197            'totalFiles'  => intval($total),
     198        ];
     199        if ($hasMore) {
    195200            $response['nextPage'] = $page + 1;
    196201        }
    197         if ( !empty( $processedFiles ) ) {
     202        if (!empty($processedFiles)) {
    198203            wp_cache_set(
    199204                $cache_key,
     
    219224     * @return \CodeConfig\IDB\App\File|array|false The processed file data if found, otherwise null.
    220225     */
    221     public function getFile( $fileKey, $returnType = 'object' ) {
     226    public function getFile($fileKey, $returnType = 'object')
     227    {
    222228        global $wpdb;
    223229        // if ($this->isValidAccount($accountId) === false) {
     
    226232        // $file = $this->fetch("SELECT * FROM {$this->tableName} WHERE id = %s AND accountId = %s", [$id, $accountId]);
    227233        $cache_key = "ccpidb_file_{$fileKey}_{$returnType}";
    228         $file = wp_cache_get( $cache_key, 'ccpidb_files' );
    229         if ( $file !== false ) {
     234        $file = wp_cache_get($cache_key, 'ccpidb_files');
     235        if ($file !== false) {
    230236            return $file;
    231237        }
    232238        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
    233         $file = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    234         if ( empty( $file ) || is_wp_error( $file ) ) {
    235             return false;
    236         }
    237         $processedFile = $this->processFile( $file, $returnType );
    238         if ( !empty( $processedFile ) ) {
    239             wp_cache_set( $cache_key, $processedFile, 'ccpidb_files' );
     239        $file = $wpdb->get_row($wpdb->prepare("SELECT * FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     240        if (empty($file) || is_wp_error($file)) {
     241            return false;
     242        }
     243        $processedFile = $this->processFile($file, $returnType);
     244        if (!empty($processedFile)) {
     245            wp_cache_set($cache_key, $processedFile, 'ccpidb_files');
    240246        }
    241247        return $processedFile;
    242248    }
    243249
    244     private function getFileByPath( $path, $accountId, $returnType = 'object' ) {
     250    private function getFileByPath($path, $accountId, $returnType = 'object')
     251    {
    245252        global $wpdb;
    246253        $cache_key = "ccpidb_file_{$path}_{$accountId}";
    247         $file = wp_cache_get( $cache_key, 'ccpidb_files' );
    248         if ( $file !== false ) {
     254        $file = wp_cache_get($cache_key, 'ccpidb_files');
     255        if ($file !== false) {
    249256            return $file;
    250257        }
    251         $file = $wpdb->get_row( $wpdb->prepare(
     258        $file = $wpdb->get_row($wpdb->prepare(
    252259            "SELECT * FROM %i WHERE path = %s AND accountId = %s",
    253260            $this->tableName,
    254261            $path,
    255262            $accountId
    256         ) );
    257         $processedFile = $this->processFile( $file, $returnType );
    258         if ( !empty( $processedFile ) ) {
    259             wp_cache_set( $cache_key, $processedFile, 'ccpidb_files' );
     263        ));
     264        $processedFile = $this->processFile($file, $returnType);
     265        if (!empty($processedFile)) {
     266            wp_cache_set($cache_key, $processedFile, 'ccpidb_files');
    260267        }
    261268        return $processedFile;
    262269    }
    263270
    264     public function getFilesByKeys( array $keys, array $args = [] ) {
    265         if ( empty( $keys ) ) {
     271    public function getFilesByKeys(array $keys, array $args = [])
     272    {
     273        if (empty($keys)) {
    266274            return [];
    267275        }
     
    279287            'accountId'      => '',
    280288        ];
    281         $args = wp_parse_args( $args, $defaults );
     289        $args = wp_parse_args($args, $defaults);
    282290        $recursive = $args['recursive'];
    283291        $moduleType = $args['moduleType'] ?? '';
    284292        $accountId = $args['accountId'] ?? null;
    285         if ( 'search-box' === $moduleType && empty( $args['search'] ) && $recursive && ($args['fileKey'] ?? '') !== '/' ) {
     293        if ('search-box' === $moduleType && empty($args['search']) && $recursive && ($args['fileKey'] ?? '') !== '/') {
    286294            $moduleType = 'file-browser';
    287295        }
     
    296304        $applyNamesFilter = $args['applyNameFilter'] ?? [];
    297305        $types = $args['types'] ?? [];
    298         $extensions = ccpidbGetAllowedModuleExtensions( $moduleType );
    299         $allowedExtensions = $this->processExtensions( $extensions, $additionalExtensions, $extensionsFilterType );
    300         ob_start();
    301         echo '<pre>';
    302         var_dump( $accountId );
    303         echo '</pre>';
    304         error_log( ob_get_clean() );
    305         $filesData = $this->getFileAttributesByKeys( $keys, [
     306        $extensions = ccpidbGetAllowedModuleExtensions($moduleType);
     307        $allowedExtensions = $this->processExtensions($extensions, $additionalExtensions, $extensionsFilterType);
     308
     309        $filesData = $this->getFileAttributesByKeys($keys, [
    306310            'id',
    307311            'path',
     
    309313            'name',
    310314            'isDir'
    311         ], $accountId );
    312         if ( is_wp_error( $filesData ) || empty( $filesData ) ) {
    313             return ( $filesData ?: [] );
    314         }
    315         if ( empty( $filesData ) ) {
     315        ], $accountId);
     316        if (is_wp_error($filesData) || empty($filesData)) {
     317            return ($filesData ?: []);
     318        }
     319        if (empty($filesData)) {
    316320            return [];
    317321        }
    318         $paths = array_filter( array_map( fn( $file ) => $file['path'] ?? null, $filesData ) );
    319         if ( empty( $paths ) ) {
     322        $paths = array_filter(array_map(fn ($file) => $file['path'] ?? null, $filesData));
     323        if (empty($paths)) {
    320324            return [];
    321325        }
    322326        global $wpdb;
    323         $sql = $wpdb->prepare( "SELECT * FROM %i WHERE 1 = 1", $this->tableName );
    324         $totalSql = $wpdb->prepare( "SELECT COUNT(*) as count FROM %i WHERE 1 = 1", $this->tableName );
    325         if ( !empty( $search ) ) {
     327        $sql = $wpdb->prepare("SELECT * FROM %i WHERE 1 = 1", $this->tableName);
     328        $totalSql = $wpdb->prepare("SELECT COUNT(*) as count FROM %i WHERE 1 = 1", $this->tableName);
     329        if (!empty($search)) {
    326330            $searchPath = [];
    327             if ( $searchScope === 'global' ) {
    328                 foreach ( $filesData as $file ) {
    329                     $searchPath[] = $this->getSuccessors( $file['path'], $file['accountId'] );
     331            if ($searchScope === 'global') {
     332                foreach ($filesData as $file) {
     333                    $searchPath[] = $this->getSuccessors($file['path'], $file['accountId']);
    330334                }
    331                 $paths = array_merge( ...$searchPath );
    332             }
    333             if ( empty( $paths ) ) {
     335                $paths = array_merge(...$searchPath);
     336            }
     337            if (empty($paths)) {
    334338                return [];
    335339            }
    336             $placeholders = implode( ',', array_fill( 0, count( $paths ), '%s' ) );
    337             if ( $searchScope === 'global' ) {
    338                 $sql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, $paths, ["%{$search}%"] ) );
    339                 $totalSql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, $paths, ["%{$search}%"] ) );
     340            $placeholders = implode(',', array_fill(0, count($paths), '%s'));
     341            if ($searchScope === 'global') {
     342                $sql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, $paths, ["%{$search}%"]));
     343                $totalSql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, $paths, ["%{$search}%"]));
    340344            } else {
    341                 $sql .= $wpdb->prepare( " AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, ["%{$search}%"] ) );
    342                 $totalSql .= $wpdb->prepare( " AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge( $paths, ["%{$search}%"] ) );
    343             }
    344         } elseif ( $recursive ) {
    345             $placeholders = implode( ',', array_fill( 0, count( $paths ), '%s' ) );
    346             if ( $moduleType === 'file-browser' ) {
    347                 $sql .= $wpdb->prepare( " AND `parent` IN ({$placeholders})", $paths );
    348                 $totalSql .= $wpdb->prepare( " AND `parent` IN ({$placeholders})", $paths );
    349             } elseif ( $moduleType === 'file-uploader' ) {
    350                 $uploadKeys = json_decode( sanitize_text_field( wp_unslash( $_COOKIE["ccpidb_file_uploader_files_{$shortcodeId}"] ?? '' ) ), true );
    351                 if ( empty( $uploadKeys ) || !is_array( $uploadKeys ) ) {
     345                $sql .= $wpdb->prepare(" AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, ["%{$search}%"]));
     346                $totalSql .= $wpdb->prepare(" AND (`parent` IN ({$placeholders})) AND `name` LIKE %s", array_merge($paths, ["%{$search}%"]));
     347            }
     348        } elseif ($recursive) {
     349            $placeholders = implode(',', array_fill(0, count($paths), '%s'));
     350            if ($moduleType === 'file-browser') {
     351                $sql .= $wpdb->prepare(" AND `parent` IN ({$placeholders})", $paths);
     352                $totalSql .= $wpdb->prepare(" AND `parent` IN ({$placeholders})", $paths);
     353            } elseif ($moduleType === 'file-uploader') {
     354                $uploadKeys = json_decode(sanitize_text_field(wp_unslash($_COOKIE["ccpidb_file_uploader_files_{$shortcodeId}"] ?? '')), true);
     355                if (empty($uploadKeys) || !is_array($uploadKeys)) {
    352356                    return [];
    353357                }
    354                 $uploadKeysPlaceholders = implode( ',', array_fill( 0, count( $uploadKeys ), '%s' ) );
    355                 $sql .= $wpdb->prepare( " AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge( $paths, $uploadKeys ) );
    356                 $totalSql .= $wpdb->prepare( " AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge( $paths, $uploadKeys ) );
     358                $uploadKeysPlaceholders = implode(',', array_fill(0, count($uploadKeys), '%s'));
     359                $sql .= $wpdb->prepare(" AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge($paths, $uploadKeys));
     360                $totalSql .= $wpdb->prepare(" AND `parent` IN ({$placeholders}) AND `fileKey` IN ({$uploadKeysPlaceholders})", array_merge($paths, $uploadKeys));
    357361            } else {
    358                 $sql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths );
    359                 $totalSql .= $wpdb->prepare( " AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths );
     362                $sql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths);
     363                $totalSql .= $wpdb->prepare(" AND (`path` IN ({$placeholders}) OR `parent` IN ({$placeholders}))", ...$paths, ...$paths);
    360364                // foreach ($paths as $path) {
    361365                //     $sql      .= $wpdb->prepare(" AND (`path` LIKE %s OR `parent` LIKE %s)", "$path%", "$path%");
     
    364368            }
    365369        } else {
    366             if ( !empty( $allowedExtensions ) && !in_array( 'folder', $allowedExtensions ) ) {
     370            if (!empty($allowedExtensions) && !in_array('folder', $allowedExtensions)) {
    367371                $allowedExtensions[] = 'folder';
    368372            }
    369             $placeholders = implode( ',', array_fill( 0, count( $paths ), '%s' ) );
    370             $sql .= $wpdb->prepare( " AND `path` IN ({$placeholders})", $paths );
    371             $totalSql .= $wpdb->prepare( " AND `path` IN ({$placeholders})", $paths );
    372         }
    373         if ( !empty( $types ) && is_array( $types ) ) {
    374             $extensions = MimeTypeManager::getExtensionsByCategory( $types );
    375             $extPlaceholders = implode( ',', array_fill( 0, count( $extensions ), '%s' ) );
    376             $sql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $extensions );
    377             $totalSql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $extensions );
    378         }
    379         if ( !empty( $allowedExtensions ) ) {
    380             $extPlaceholders = implode( ',', array_fill( 0, count( $allowedExtensions ), '%s' ) );
    381             $sql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $allowedExtensions );
    382             $totalSql .= $wpdb->prepare( " AND `extension` IN ({$extPlaceholders})", $allowedExtensions );
    383         }
    384         if ( !empty( $args['orderBy'] ) && !empty( $args['order'] ) ) {
     373            $placeholders = implode(',', array_fill(0, count($paths), '%s'));
     374            $sql .= $wpdb->prepare(" AND `path` IN ({$placeholders})", $paths);
     375            $totalSql .= $wpdb->prepare(" AND `path` IN ({$placeholders})", $paths);
     376        }
     377        if (!empty($types) && is_array($types)) {
     378            $extensions = MimeTypeManager::getExtensionsByCategory($types);
     379            $extPlaceholders = implode(',', array_fill(0, count($extensions), '%s'));
     380            $sql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $extensions);
     381            $totalSql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $extensions);
     382        }
     383        if (!empty($allowedExtensions)) {
     384            $extPlaceholders = implode(',', array_fill(0, count($allowedExtensions), '%s'));
     385            $sql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $allowedExtensions);
     386            $totalSql .= $wpdb->prepare(" AND `extension` IN ({$extPlaceholders})", $allowedExtensions);
     387        }
     388        if (!empty($args['orderBy']) && !empty($args['order'])) {
    385389            $allowedOrderBy = [
    386390                'id',
     
    390394                'updatedAt'
    391395            ];
    392             $orderBy = $this->sanitizeOrderBy( $args['orderBy'], $allowedOrderBy );
    393             $order = $this->sanitizeOrder( $args['order'] );
    394             $offset = $this->sanitizePagination( $args['page'], $args['perPage'] );
    395             $sql .= $wpdb->prepare( " ORDER BY (CASE WHEN extension = 'folder' THEN 0 ELSE 1 END), `{$orderBy}` {$order} LIMIT %d OFFSET %d", $offset['perPage'], $offset['offset'] );
     396            $orderBy = $this->sanitizeOrderBy($args['orderBy'], $allowedOrderBy);
     397            $order = $this->sanitizeOrder($args['order']);
     398            $offset = $this->sanitizePagination($args['page'], $args['perPage']);
     399            $sql .= $wpdb->prepare(" ORDER BY (CASE WHEN extension = 'folder' THEN 0 ELSE 1 END), `{$orderBy}` {$order} LIMIT %d OFFSET %d", $offset['perPage'], $offset['offset']);
    396400        }
    397401        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    398         $files = $wpdb->get_results( $sql );
     402        $files = $wpdb->get_results($sql);
    399403        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching WordPress.DB.PreparedSQL.NotPrepared
    400         $totalCount = $wpdb->get_row( $totalSql );
    401         if ( empty( $files ) || is_wp_error( $files ) || is_wp_error( $totalCount ) ) {
     404        $totalCount = $wpdb->get_row($totalSql);
     405        if (empty($files) || is_wp_error($files) || is_wp_error($totalCount)) {
    402406            return [];
    403407        }
    404         $files = $this->processFiles( $files, $returnType );
    405         $totalFiles = ( isset( $totalCount->count ) ? (int) $totalCount->count : count( $files ) );
     408        $files = $this->processFiles($files, $returnType);
     409        $totalFiles = (isset($totalCount->count) ? (int) $totalCount->count : count($files));
    406410        $page = $offset['page'] ?? 1;
    407         $totalPage = ceil( $totalFiles / ($offset['perPage'] ?? 1) );
     411        $totalPage = ceil($totalFiles / ($offset['perPage'] ?? 1));
    408412        $response = [
    409413            'breadcrumb'  => [[
    410414                'fileKey' => '/',
    411                 'name'    => __( 'Home', 'integrate-dropbox' ),
     415                'name'    => __('Home', 'integrate-dropbox'),
    412416            ]],
    413             'totalPage'   => ( $totalPage < 1 ? 1 : $totalPage ),
     417            'totalPage'   => ($totalPage < 1 ? 1 : $totalPage),
    414418            'hasMore'     => $totalPage > $page,
    415419            'currentPage' => $page,
     
    417421            'totalFiles'  => $totalFiles,
    418422        ];
    419         if ( $response['hasMore'] ) {
     423        if ($response['hasMore']) {
    420424            $response['nextPage'] = $page + 1;
    421425        }
     
    423427    }
    424428
    425     public function getFolderTree( $accountId, ... $rootPaths ) {
     429    public function getFolderTree($accountId, ... $rootPaths)
     430    {
    426431        global $wpdb;
    427432        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
    428         $sql = $wpdb->prepare( "SELECT fileKey, name, parent, path FROM %i WHERE `extension` = 'folder' AND accountId = %s", $this->tableName, $accountId );
    429         if ( !empty( $rootPaths ) && !in_array( '/', $rootPaths, true ) ) {
     433        $sql = $wpdb->prepare("SELECT fileKey, name, parent, path FROM %i WHERE `extension` = 'folder' AND accountId = %s", $this->tableName, $accountId);
     434        if (!empty($rootPaths) && !in_array('/', $rootPaths, true)) {
    430435            $sql .= " AND ( 0=1 ";
    431             foreach ( $rootPaths as $rootPath ) {
    432                 $sql .= $wpdb->prepare( " OR path LIKE %s OR path LIKE %s", "{$rootPath}/%", "{$rootPath}" );
     436            foreach ($rootPaths as $rootPath) {
     437                $sql .= $wpdb->prepare(" OR path LIKE %s OR path LIKE %s", "{$rootPath}/%", "{$rootPath}");
    433438            }
    434439            $sql .= " ) ";
    435440        }
    436         $files = $wpdb->get_results( $sql, ARRAY_A );
    437         if ( empty( $files ) || is_wp_error( $files ) ) {
     441        $files = $wpdb->get_results($sql, ARRAY_A);
     442        if (empty($files) || is_wp_error($files)) {
    438443            return [];
    439444        }
    440         return $this->processFolderTree( $files, $rootPaths );
    441     }
    442 
    443     public function addFile( array $data ) {
     445        return $this->processFolderTree($files, $rootPaths);
     446    }
     447
     448    public function addFile(array $data)
     449    {
    444450        global $wpdb;
    445451        $file = [
     
    448454            'path'            => $data['path'] ?? '',
    449455            'name'            => $data['name'] ?? null,
    450             'size'            => intval( $data['size'] ?? 0 ),
     456            'size'            => intval($data['size'] ?? 0),
    451457            'parent'          => $data['parent'] ?? null,
    452458            'accountId'       => $data['accountId'] ?? '',
     
    457463            'sharedLink'      => $data['sharedLink'] ?? null,
    458464            'isDir'           => $data['isDir'] ?? null,
    459             'permissions'     => maybe_serialize( $data['permissions'] ?? [] ),
     465            'permissions'     => maybe_serialize($data['permissions'] ?? []),
    460466            'hasOwnThumbnail' => $data['hasOwnThumbnail'] ?? null,
    461467            'icon'            => $data['icon'] ?? null,
    462             'additionalData'  => maybe_serialize( $data['additionalData'] ?? [] ),
    463             'createdAt'       => current_time( 'mysql' ),
    464             'updatedAt'       => current_time( 'mysql' ),
    465         ];
    466         if ( empty( $file['fileId'] ) || empty( $file['accountId'] ) ) {
    467             return new WP_Error(404, __( 'Missing file ID or account ID.', 'integrate-dropbox' ));
     468            'additionalData'  => maybe_serialize($data['additionalData'] ?? []),
     469            'createdAt'       => current_time('mysql'),
     470            'updatedAt'       => current_time('mysql'),
     471        ];
     472        if (empty($file['fileId']) || empty($file['accountId'])) {
     473            return new WP_Error(404, __('Missing file ID or account ID.', 'integrate-dropbox'));
    468474        }
    469475        $format = [
     
    506512            '%s',
    507513        ];
    508         if ( !empty( $data['thumbnailRatio'] ) ) {
     514        if (!empty($data['thumbnailRatio'])) {
    509515            $file['thumbnailRatio'] = $data['thumbnailRatio'];
    510516            $format[] = '%s';
    511517            // thumbnailRatio
    512518        }
    513         if ( $this->isCachedFile( $file["fileKey"] ) ) {
     519        if ($this->isCachedFile($file["fileKey"])) {
    514520            unset($file["id"]);
    515521            unset($file["fileId"]);
     
    549555                '%s',
    550556            ];
    551             if ( !empty( $data['thumbnailRatio'] ) ) {
     557            if (!empty($data['thumbnailRatio'])) {
    552558                $updateFormat[] = '%s';
    553559                // thumbnailRatio
     
    563569            );
    564570        }
    565         return $wpdb->insert( $this->tableName, $file, $format );
    566     }
    567 
    568     public function deleteFiles( $fileKeys ) : int {
    569         global $wpdb;
    570         if ( empty( $fileKeys ) ) {
     571        return $wpdb->insert($this->tableName, $file, $format);
     572    }
     573
     574    public function deleteFiles($fileKeys): int
     575    {
     576        global $wpdb;
     577        if (empty($fileKeys)) {
    571578            return 0;
    572579        }
    573580        $fileKeys = (array) $fileKeys;
    574         $files = $this->getFileAttributesByKeys( $fileKeys, ['accountId', 'path', 'isDir'] );
    575         if ( empty( $files ) ) {
     581        $files = $this->getFileAttributesByKeys($fileKeys, ['accountId', 'path', 'isDir']);
     582        if (empty($files)) {
    576583            return 0;
    577584        }
    578585        $filePaths = [];
    579586        $folderRefs = [];
    580         foreach ( $files as $file ) {
    581             if ( empty( $file['path'] ) || empty( $file['accountId'] ) ) {
     587        foreach ($files as $file) {
     588            if (empty($file['path']) || empty($file['accountId'])) {
    582589                continue;
    583590            }
    584             if ( !empty( $file['isDir'] ) ) {
     591            if (!empty($file['isDir'])) {
    585592                $folderRefs[] = [$file['path'], $file['accountId']];
    586593            } else {
     
    588595            }
    589596        }
    590         foreach ( $folderRefs as [$path, $accountId] ) {
    591             $filePaths = array_merge( $filePaths, (array) $this->getSuccessors( $path, $accountId ) );
    592         }
    593         if ( empty( $filePaths ) ) {
     597        foreach ($folderRefs as [$path, $accountId]) {
     598            $filePaths = array_merge($filePaths, (array) $this->getSuccessors($path, $accountId));
     599        }
     600        if (empty($filePaths)) {
    594601            return 0;
    595602        }
    596         $placeholders = implode( ',', array_fill( 0, count( $filePaths ), '%s' ) );
    597         return (int) $wpdb->query( $wpdb->prepare( "DELETE FROM %i WHERE path IN ({$placeholders}) OR parent IN ({$placeholders})", array_merge( [$this->tableName], $filePaths, $filePaths ) ) );
    598     }
    599 
    600     public function deleteFilesByAccount( $accountId ) {
    601         if ( empty( $accountId ) ) {
     603        $placeholders = implode(',', array_fill(0, count($filePaths), '%s'));
     604        return (int) $wpdb->query($wpdb->prepare("DELETE FROM %i WHERE path IN ({$placeholders}) OR parent IN ({$placeholders})", array_merge([$this->tableName], $filePaths, $filePaths)));
     605    }
     606
     607    public function deleteFilesByAccount($accountId)
     608    {
     609        if (empty($accountId)) {
    602610            return 0;
    603611        }
    604         return $this->deleteRecords( [
     612        return $this->deleteRecords([
    605613            'accountId' => $accountId,
    606         ] );
    607     }
    608 
    609     public function isCachedFile( $fileKey ) {
    610         global $wpdb;
    611         $folder = $wpdb->get_row( $wpdb->prepare( "SELECT fileKey FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    612         return !empty( $folder );
    613     }
    614 
    615     public function getPathById( $fileId ) {
    616         global $wpdb;
    617         $file = $wpdb->get_row( $wpdb->prepare( "SELECT path FROM %i WHERE fileId = %s", $this->tableName, $fileId ) );
    618         if ( empty( $file ) || is_wp_error( $file ) ) {
     614        ]);
     615    }
     616
     617    public function isCachedFile($fileKey)
     618    {
     619        global $wpdb;
     620        $folder = $wpdb->get_row($wpdb->prepare("SELECT fileKey FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     621        return !empty($folder);
     622    }
     623
     624    public function getPathById($fileId)
     625    {
     626        global $wpdb;
     627        $file = $wpdb->get_row($wpdb->prepare("SELECT path FROM %i WHERE fileId = %s", $this->tableName, $fileId));
     628        if (empty($file) || is_wp_error($file)) {
    619629            return false;
    620630        }
     
    622632    }
    623633
    624     public function getPathsByKeys( $fileKeys ) {
    625         global $wpdb;
    626         $isString = \is_string( $fileKeys );
    627         if ( $isString ) {
     634    public function getPathsByKeys($fileKeys)
     635    {
     636        global $wpdb;
     637        $isString = \is_string($fileKeys);
     638        if ($isString) {
    628639            $fileKeys = [$fileKeys];
    629640        }
    630         $placeholders = implode( ',', array_fill( 0, count( $fileKeys ), '%s' ) );
    631         $preparedQuery = $wpdb->prepare( "SELECT path FROM %i WHERE fileKey IN ({$placeholders})", array_merge( [$this->tableName], $fileKeys ) );
    632         $results = $wpdb->get_results( $preparedQuery );
    633         if ( $isString && \count( $results ) === 1 ) {
     641        $placeholders = implode(',', array_fill(0, count($fileKeys), '%s'));
     642        $preparedQuery = $wpdb->prepare("SELECT path FROM %i WHERE fileKey IN ({$placeholders})", array_merge([$this->tableName], $fileKeys));
     643        $results = $wpdb->get_results($preparedQuery);
     644        if ($isString && \count($results) === 1) {
    634645            return $results[0]->path;
    635646        }
    636647        $paths = [];
    637         foreach ( $results as $row ) {
     648        foreach ($results as $row) {
    638649            $paths[] = $row->path;
    639650        }
     
    650661        global $wpdb;
    651662        // Validate inputs
    652         if ( empty( $columns ) || empty( $fileKeys ) ) {
     663        if (empty($columns) || empty($fileKeys)) {
    653664            return [];
    654665        }
    655666        // Filter and sanitize columns
    656         $sanitizedColumns = array_filter( $columns, fn( $col ) => in_array( $col, self::COLUMNS, true ) );
    657         if ( empty( $sanitizedColumns ) ) {
     667        $sanitizedColumns = array_filter($columns, fn ($col) => in_array($col, self::COLUMNS, true));
     668        if (empty($sanitizedColumns)) {
    658669            return [];
    659670        }
    660671        // Validate WHERE clause columns
    661         if ( !empty( $where ) ) {
    662             foreach ( array_keys( $where ) as $whereColumn ) {
    663                 if ( !in_array( $whereColumn, self::COLUMNS, true ) ) {
     672        if (!empty($where)) {
     673            foreach (array_keys($where) as $whereColumn) {
     674                if (!in_array($whereColumn, self::COLUMNS, true)) {
    664675                    return [];
    665676                }
     
    667678        }
    668679        // Prepare column identifiers using %i placeholders for security
    669         $columnPlaceholders = implode( ',', array_fill( 0, count( $sanitizedColumns ), '%i' ) );
    670         $keyPlaceholders = implode( ',', array_fill( 0, count( $fileKeys ), '%s' ) );
     680        $columnPlaceholders = implode(',', array_fill(0, count($sanitizedColumns), '%i'));
     681        $keyPlaceholders = implode(',', array_fill(0, count($fileKeys), '%s'));
    671682        // Build the base query with proper placeholders
    672683        $sql = "SELECT {$columnPlaceholders} FROM %i WHERE fileKey IN ({$keyPlaceholders})";
    673         $params = array_merge( $sanitizedColumns, [$this->tableName], $fileKeys );
     684        $params = array_merge($sanitizedColumns, [$this->tableName], $fileKeys);
    674685        // Add additional WHERE conditions with proper format specifiers
    675         if ( !empty( $where ) ) {
     686        if (!empty($where)) {
    676687            $whereConditions = [];
    677688            $whereIndex = 0;
    678             foreach ( $where as $column => $value ) {
     689            foreach ($where as $column => $value) {
    679690                // Use provided format or default to %s
    680                 $format = ( !empty( $where_format[$whereIndex] ) ? $where_format[$whereIndex] : '%s' );
     691                $format = (!empty($where_format[$whereIndex]) ? $where_format[$whereIndex] : '%s');
    681692                $whereConditions[] = "%i = {$format}";
    682693                $params[] = $column;
     
    684695                $whereIndex++;
    685696            }
    686             $sql .= " AND " . implode( ' AND ', $whereConditions );
    687         }
    688         $preparedQuery = $wpdb->prepare( $sql, $params );
    689         $results = $wpdb->get_results( $preparedQuery, $returnType );
    690         if ( empty( $results ) || is_wp_error( $results ) ) {
     697            $sql .= " AND " . implode(' AND ', $whereConditions);
     698        }
     699        $preparedQuery = $wpdb->prepare($sql, $params);
     700        $results = $wpdb->get_results($preparedQuery, $returnType);
     701        if (empty($results) || is_wp_error($results)) {
    691702            return [];
    692703        }
     
    694705    }
    695706
    696     public function getAccountIdByFileKey( $fileKey ) {
    697         global $wpdb;
    698         $file = $wpdb->get_row( $wpdb->prepare( "SELECT accountId FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    699         if ( empty( $file ) || is_wp_error( $file ) ) {
     707    public function getAccountIdByFileKey($fileKey)
     708    {
     709        global $wpdb;
     710        $file = $wpdb->get_row($wpdb->prepare("SELECT accountId FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     711        if (empty($file) || is_wp_error($file)) {
    700712            return false;
    701713        }
     
    703715    }
    704716
    705     public function updateThumbnail( $fileKey, $url ) {
     717    public function updateThumbnail($fileKey, $url)
     718    {
    706719        global $wpdb;
    707720        return $wpdb->update(
     
    740753        $clean = false
    741754    ) {
    742         if ( $path === '' || $path === '/' || empty( $accountId ) ) {
    743             return new WP_Error(400, __( 'Invalid path or account ID.', 'integrate-dropbox' ));
    744         }
    745         global $wpdb;
    746         if ( $clean === false ) {
    747             $file = $this->getFileByPath( $path, $accountId, 'array' );
    748             if ( is_wp_error( $file ) ) {
     755        if ($path === '' || $path === '/' || empty($accountId)) {
     756            return new WP_Error(400, __('Invalid path or account ID.', 'integrate-dropbox'));
     757        }
     758        global $wpdb;
     759        if ($clean === false) {
     760            $file = $this->getFileByPath($path, $accountId, 'array');
     761            if (is_wp_error($file)) {
    749762                return $file;
    750763            }
    751764            $existingData = $file['metaData'] ?? [];
    752             if ( is_array( $existingData ) ) {
    753                 $metaData = array_merge( $existingData, $metaData );
     765            if (is_array($existingData)) {
     766                $metaData = array_merge($existingData, $metaData);
    754767            }
    755768        }
    756769        $filteredMetaData = [];
    757         foreach ( self::META_DATA as $key ) {
    758             if ( isset( $metaData[$key] ) ) {
     770        foreach (self::META_DATA as $key) {
     771            if (isset($metaData[$key])) {
    759772                $filteredMetaData[$key] = $metaData[$key];
    760773            }
     
    763776            $this->tableName,
    764777            [
    765                 'metaData' => maybe_serialize( $filteredMetaData ),
     778                'metaData' => maybe_serialize($filteredMetaData),
    766779            ],
    767780            [
     
    774787    }
    775788
    776     public function getBreadcrumbByKey( $key, $args = [] ) {
     789    public function getBreadcrumbByKey($key, $args = [])
     790    {
    777791        $defaults = [
    778792            'rootFileKey'   => null,
    779793            'rootFolderKey' => '/',
    780794        ];
    781         $args = wp_parse_args( $args, $defaults );
     795        $args = wp_parse_args($args, $defaults);
    782796        $rootFileKey = $args['rootFileKey'];
    783797        $rootFolderKey = $args['rootFolderKey'];
    784798        $home = [[
    785799            'fileKey' => '/',
    786             'name'    => __( 'Home', 'integrate-dropbox' ),
     800            'name'    => __('Home', 'integrate-dropbox'),
    787801        ]];
    788802        // Empty or root key
    789         if ( empty( $key ) || $key === '/' || $key === $rootFolderKey ) {
     803        if (empty($key) || $key === '/' || $key === $rootFolderKey) {
    790804            return $home;
    791805        }
    792806        // Resolve root folder key if rootFileKey is provided
    793         if ( $rootFileKey !== null && $rootFolderKey === '/' ) {
    794             $rootFile = $this->getFile( $rootFileKey, 'array' );
    795             if ( is_wp_error( $rootFile ) ) {
     807        if ($rootFileKey !== null && $rootFolderKey === '/') {
     808            $rootFile = $this->getFile($rootFileKey, 'array');
     809            if (is_wp_error($rootFile)) {
    796810                return $home;
    797811            }
    798812            $parentPath = $rootFile['parent'] ?? null;
    799             if ( $parentPath ) {
    800                 $rootFolder = $this->getFileByPath( $parentPath, $rootFile['accountId'] ?? '', 'array' );
    801                 if ( !is_wp_error( $rootFolder ) ) {
     813            if ($parentPath) {
     814                $rootFolder = $this->getFileByPath($parentPath, $rootFile['accountId'] ?? '', 'array');
     815                if (!is_wp_error($rootFolder)) {
    802816                    $rootFolderKey = $rootFolder['fileKey'] ?? '/';
    803817                }
    804818            }
    805819        }
    806         $file = $this->getFile( $key, 'array' );
    807         if ( is_wp_error( $file ) ) {
     820        $file = $this->getFile($key, 'array');
     821        if (is_wp_error($file)) {
    808822            return $home;
    809823        }
    810824        $fileId = $file['fileId'] ?? null;
    811825        $accountId = $file['accountId'] ?? null;
    812         if ( !$fileId || !$accountId ) {
     826        if (!$fileId || !$accountId) {
    813827            return $home;
    814828        }
     
    816830        $breadcrumb = [[
    817831            'fileKey' => $key,
    818             'name'    => $file['name'] ?? __( 'Unknown Folder', 'integrate-dropbox' ),
     832            'name'    => $file['name'] ?? __('Unknown Folder', 'integrate-dropbox'),
    819833        ]];
    820834        $parentPath = $file['parent'] ?? null;
    821835        // Stop if no parent
    822         if ( empty( $parentPath ) ) {
     836        if (empty($parentPath)) {
    823837            return $breadcrumb;
    824838        }
    825839        // Resolve parent folder key
    826840        $parentFolderKey = '/';
    827         if ( $parentPath !== '/' ) {
    828             $parentFolder = $this->getFileByPath( $parentPath, $accountId, 'array' );
    829             if ( is_wp_error( $parentFolder ) ) {
     841        if ($parentPath !== '/') {
     842            $parentFolder = $this->getFileByPath($parentPath, $accountId, 'array');
     843            if (is_wp_error($parentFolder)) {
    830844                return $home;
    831845            }
     
    833847        }
    834848        // Stop at root folder
    835         if ( $parentFolderKey === '/' || $parentFolderKey === $rootFolderKey ) {
    836             return array_merge( $breadcrumb, $home );
     849        if ($parentFolderKey === '/' || $parentFolderKey === $rootFolderKey) {
     850            return array_merge($breadcrumb, $home);
    837851        }
    838852        // Recursive parent breadcrumb
    839         $parentBreadcrumb = $this->getBreadcrumbByKey( $parentFolderKey, [
     853        $parentBreadcrumb = $this->getBreadcrumbByKey($parentFolderKey, [
    840854            'rootFolderKey' => $rootFolderKey,
    841         ] );
    842         if ( is_wp_error( $parentBreadcrumb ) ) {
     855        ]);
     856        if (is_wp_error($parentBreadcrumb)) {
    843857            return $parentBreadcrumb;
    844858        }
    845         return array_merge( $breadcrumb, $parentBreadcrumb );
    846     }
    847 
    848     public function getFileAttributesByKeys( array $keys, array $attributes = ['id'], $accountId = null ) {
    849         if ( empty( $keys ) ) {
     859        return array_merge($breadcrumb, $parentBreadcrumb);
     860    }
     861
     862    public function getFileAttributesByKeys(array $keys, array $attributes = ['id'], $accountId = null)
     863    {
     864        if (empty($keys)) {
    850865            return [];
    851866        }
    852867        global $wpdb;
    853         $placeholders = implode( ',', array_fill( 0, count( $keys ), '%s' ) );
    854         $preparedQuery = $wpdb->prepare( "SELECT * FROM %i WHERE `fileKey` IN ({$placeholders})", array_merge( [$this->tableName], $keys ) );
    855         if ( !empty( $accountId ) ) {
    856             $preparedQuery .= $wpdb->prepare( " AND `accountId` = %s", $accountId );
    857         }
    858         $cacheKey = "ccpidb_file_attributes_" . md5( $preparedQuery );
    859         if ( false !== ($cached = wp_cache_get( $cacheKey, 'ccpidb_files' )) ) {
     868        $placeholders = implode(',', array_fill(0, count($keys), '%s'));
     869        $preparedQuery = $wpdb->prepare("SELECT * FROM %i WHERE `fileKey` IN ({$placeholders})", array_merge([$this->tableName], $keys));
     870        if (!empty($accountId)) {
     871            $preparedQuery .= $wpdb->prepare(" AND `accountId` = %s", $accountId);
     872        }
     873        $cacheKey = "ccpidb_file_attributes_" . md5($preparedQuery);
     874        if (false !== ($cached = wp_cache_get($cacheKey, 'ccpidb_files'))) {
    860875            return $cached;
    861876        }
    862         $files = $wpdb->get_results( $preparedQuery );
    863         if ( empty( $files ) ) {
     877        $files = $wpdb->get_results($preparedQuery);
     878        if (empty($files)) {
    864879            return [];
    865880        }
    866         $processedFiles = $this->processFiles( $files, 'object' );
    867         if ( count( $attributes ) === 1 ) {
     881        $processedFiles = $this->processFiles($files, 'object');
     882        if (count($attributes) === 1) {
    868883            $attr = $attributes[0];
    869884            $result = [];
    870             foreach ( $processedFiles as $file ) {
     885            foreach ($processedFiles as $file) {
    871886                $result[] = $file->{$attr} ?? null;
    872887            }
    873             wp_cache_set( $cacheKey, $result, 'ccpidb_files' );
     888            wp_cache_set($cacheKey, $result, 'ccpidb_files');
    874889            return $result;
    875890        }
    876891        $result = [];
    877         foreach ( $processedFiles as $file ) {
     892        foreach ($processedFiles as $file) {
    878893            $fileData = [];
    879             foreach ( $attributes as $attr ) {
     894            foreach ($attributes as $attr) {
    880895                $fileData[$attr] = $file->{$attr} ?? null;
    881896            }
    882897            $result[] = $fileData;
    883898        }
    884         wp_cache_set( $cacheKey, $result, 'ccpidb_files' );
     899        wp_cache_set($cacheKey, $result, 'ccpidb_files');
    885900        return $result;
    886901    }
    887902
    888     public function getSuccessors( $parentPath, $accountId ) {
     903    public function getSuccessors($parentPath, $accountId)
     904    {
    889905        $successor = [];
    890         $folders = $this->getChildFolderIds( $parentPath, $accountId );
    891         foreach ( $folders as $folderRow ) {
     906        $folders = $this->getChildFolderIds($parentPath, $accountId);
     907        foreach ($folders as $folderRow) {
    892908            $folderPath = $folderRow['path'];
    893909            $successor[] = $folderPath;
    894             $childFolders = $this->getChildFolderIds( $folderPath, $accountId );
    895             if ( !empty( $childFolders ) ) {
    896                 $successor = array_merge( $successor, $this->getSuccessors( $folderPath, $accountId ) );
     910            $childFolders = $this->getChildFolderIds($folderPath, $accountId);
     911            if (!empty($childFolders)) {
     912                $successor = array_merge($successor, $this->getSuccessors($folderPath, $accountId));
    897913            }
    898914        }
    899915        $successor[] = $parentPath;
    900         return array_unique( $successor );
    901     }
    902 
    903     public function getAllPhotos( $args = [] ) {
     916        return array_unique($successor);
     917    }
     918
     919    public function getAllPhotos($args = [])
     920    {
    904921        $defaults = [
    905922            'perPage' => 40,
     
    908925            'order'   => 'desc',
    909926        ];
    910         $args = wp_parse_args( $args, $defaults );
     927        $args = wp_parse_args($args, $defaults);
    911928        $perPage = (int) $args['perPage'];
    912929        $page = (int) $args['page'];
    913         $orderBy = $this->sanitizeOrderBy( $args['orderBy'], [
     930        $orderBy = $this->sanitizeOrderBy($args['orderBy'], [
    914931            'name',
    915932            'createdAt',
    916933            'updatedAt',
    917934            'size'
    918         ] );
    919         $order = $this->sanitizeOrder( $args['order'] );
     935        ]);
     936        $order = $this->sanitizeOrder($args['order']);
    920937        $offset = ($page - 1) * $perPage;
    921938        global $wpdb;
    922939        $cache_key = "ccpidb_all_photos_{$perPage}_{$page}_{$orderBy}_{$order}";
    923         $photos = wp_cache_get( $cache_key, 'ccpidb_files' );
    924         if ( !empty( $photos ) ) {
     940        $photos = wp_cache_get($cache_key, 'ccpidb_files');
     941        if (!empty($photos)) {
    925942            return $photos;
    926943        }
    927         $photos = $wpdb->get_results( $wpdb->prepare(
     944        $photos = $wpdb->get_results($wpdb->prepare(
    928945            "SELECT * FROM %i WHERE mimeType LIKE %s ORDER BY %i {$order} LIMIT %d OFFSET %d",
    929946            $this->tableName,
     
    932949            $perPage,
    933950            $offset
    934         ) );
    935         if ( is_wp_error( $photos ) ) {
     951        ));
     952        if (is_wp_error($photos)) {
    936953            return $photos;
    937954        }
    938         $total = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM %i WHERE mimeType LIKE %s", $this->tableName, 'image/%' ) );
    939         if ( is_wp_error( $total ) ) {
     955        $total = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM %i WHERE mimeType LIKE %s", $this->tableName, 'image/%'));
     956        if (is_wp_error($total)) {
    940957            return $total;
    941958        }
    942         $totalPages = ceil( $total / $perPage );
     959        $totalPages = ceil($total / $perPage);
    943960        $hasMore = $page < $totalPages;
    944961        $response = [
     
    948965            'totalPages' => (int) $totalPages,
    949966            'hasMore'    => $hasMore,
    950             'photos'     => $this->processFiles( $photos ),
    951         ];
    952         if ( $hasMore ) {
     967            'photos'     => $this->processFiles($photos),
     968        ];
     969        if ($hasMore) {
    953970            $response['nextPage'] = $page + 1;
    954971        }
    955         if ( !empty( $photos ) ) {
    956             wp_cache_set( $cache_key, $response, 'ccpidb_files' );
     972        if (!empty($photos)) {
     973            wp_cache_set($cache_key, $response, 'ccpidb_files');
    957974        }
    958975        return $response;
    959976    }
    960977
    961     public function searchFiles( $query, $options = [] ) {
    962         global $wpdb;
    963         if ( empty( $query ) || empty( $options['accountId'] ) ) {
    964             return new WP_Error('invalid_query', __( 'Search query and account ID are required.', 'integrate-dropbox' ));
     978    public function searchFiles($query, $options = [])
     979    {
     980        global $wpdb;
     981        if (empty($query) || empty($options['accountId'])) {
     982            return new WP_Error('invalid_query', __('Search query and account ID are required.', 'integrate-dropbox'));
    965983        }
    966984        $defaults = [
     
    972990            'order'   => 'ASC',
    973991        ];
    974         $options = wp_parse_args( $options, $defaults );
    975         $order = $this->sanitizeOrder( $options['order'] );
    976         $orderBy = $this->sanitizeOrderBy( $options['orderBy'], [
     992        $options = wp_parse_args($options, $defaults);
     993        $order = $this->sanitizeOrder($options['order']);
     994        $orderBy = $this->sanitizeOrderBy($options['orderBy'], [
    977995            'name',
    978996            'createdAt',
    979997            'updatedAt',
    980998            'size'
    981         ] );
    982         $pagination = $this->sanitizePagination( $options['page'], $options['perPage'] );
     999        ]);
     1000        $pagination = $this->sanitizePagination($options['page'], $options['perPage']);
    9831001        $perPage = $pagination['perPage'];
    9841002        $offset = $pagination['offset'];
    9851003        $page = $pagination['page'];
    986         $searchPattern = '%' . $wpdb->esc_like( $query ) . '%';
     1004        $searchPattern = '%' . $wpdb->esc_like($query) . '%';
    9871005        $sql = $wpdb->prepare(
    9881006            "SELECT * FROM %i WHERE accountId = %s AND name LIKE %s",
     
    9971015            $searchPattern
    9981016        );
    999         if ( $options['scope'] === 'folder' && !empty( $options['path'] ) ) {
    1000             $sql .= $wpdb->prepare( " AND parent = %s", $options['path'] );
    1001             $totalSql .= $wpdb->prepare( " AND parent = %s", $options['path'] );
    1002         }
    1003         if ( !empty( $options['types'] ) && is_array( $options['types'] ) ) {
    1004             $extensions = MimeTypeManager::getExtensionsByCategory( $options['types'] );
    1005             if ( !empty( $extensions ) ) {
    1006                 $extPlaceholders = implode( ',', array_fill( 0, count( $extensions ), '%s' ) );
    1007                 $sql .= $wpdb->prepare( " AND extension IN ({$extPlaceholders})", $extensions );
    1008                 $totalSql .= $wpdb->prepare( " AND extension IN ({$extPlaceholders})", $extensions );
     1017        if ($options['scope'] === 'folder' && !empty($options['path'])) {
     1018            $sql .= $wpdb->prepare(" AND parent = %s", $options['path']);
     1019            $totalSql .= $wpdb->prepare(" AND parent = %s", $options['path']);
     1020        }
     1021        if (!empty($options['types']) && is_array($options['types'])) {
     1022            $extensions = MimeTypeManager::getExtensionsByCategory($options['types']);
     1023            if (!empty($extensions)) {
     1024                $extPlaceholders = implode(',', array_fill(0, count($extensions), '%s'));
     1025                $sql .= $wpdb->prepare(" AND extension IN ({$extPlaceholders})", $extensions);
     1026                $totalSql .= $wpdb->prepare(" AND extension IN ({$extPlaceholders})", $extensions);
    10091027            }
    10101028        }
     
    10151033            $offset
    10161034        );
    1017         $cache_key = "ccpidb_search_{$options['accountId']}_" . md5( $query . serialize( $options ) );
    1018         $cached = wp_cache_get( $cache_key, 'ccpidb_files' );
    1019         if ( !empty( $cached ) ) {
     1035        $cache_key = "ccpidb_search_{$options['accountId']}_" . md5($query . serialize($options));
     1036        $cached = wp_cache_get($cache_key, 'ccpidb_files');
     1037        if (!empty($cached)) {
    10201038            return $cached;
    10211039        }
    1022         $results = $wpdb->get_results( $sql );
    1023         $totalFile = $wpdb->get_var( $totalSql );
    1024         if ( is_wp_error( $results ) || is_wp_error( $totalFile ) ) {
     1040        $results = $wpdb->get_results($sql);
     1041        $totalFile = $wpdb->get_var($totalSql);
     1042        if (is_wp_error($results) || is_wp_error($totalFile)) {
    10251043            return $results;
    10261044        }
    1027         if ( empty( $results ) || $totalFile == 0 ) {
     1045        if (empty($results) || $totalFile == 0) {
    10281046            return [];
    10291047        }
    10301048        $response = [
    10311049            'total'       => (int) $totalFile,
    1032             'files'       => $this->processFiles( $results ),
     1050            'files'       => $this->processFiles($results),
    10331051            'perPage'     => $perPage,
    1034             'totalPages'  => ceil( $totalFile / $perPage ),
     1052            'totalPages'  => ceil($totalFile / $perPage),
    10351053            'currentPage' => $page,
    10361054            'hasMore'     => $page * $perPage < $totalFile,
    10371055        ];
    1038         if ( $response['hasMore'] ) {
     1056        if ($response['hasMore']) {
    10391057            $response['nextPage'] = $page + 1;
    10401058        }
    1041         if ( !empty( $results ) ) {
    1042             wp_cache_set( $cache_key, $response, 'ccpidb_files' );
     1059        if (!empty($results)) {
     1060            wp_cache_set($cache_key, $response, 'ccpidb_files');
    10431061        }
    10441062        return $response;
    10451063    }
    10461064
    1047     public function getSharedKey( $fileKey, $options = [] ) {
     1065    public function getSharedKey($fileKey, $options = [])
     1066    {
    10481067        $defaults = [
    10491068            'expireIn' => 3600,
    10501069            'password' => null,
    10511070        ];
    1052         $options = wp_parse_args( $options, $defaults );
    1053         $expireIn = intval( $options['expireIn'] );
    1054         $password = sanitize_text_field( $options['password'] ?? null );
    1055         $expiry = ( $expireIn > 0 ? time() + $expireIn : 0 );
    1056         $passwordHash = ( !empty( $password ) ? md5( $password ) : '' );
    1057         $sharedData = $this->getSharedData( $fileKey );
    1058         $key = md5( "{$fileKey}|{$expiry}|{$passwordHash}" );
    1059         if ( !empty( $sharedData[$key] ) && $sharedData[$key]['expiry'] >= time() ) {
     1071        $options = wp_parse_args($options, $defaults);
     1072        $expireIn = intval($options['expireIn']);
     1073        $password = sanitize_text_field($options['password'] ?? null);
     1074        $expiry = ($expireIn > 0 ? time() + $expireIn : 0);
     1075        $passwordHash = (!empty($password) ? md5($password) : '');
     1076        $sharedData = $this->getSharedData($fileKey);
     1077        $key = md5("{$fileKey}|{$expiry}|{$passwordHash}");
     1078        if (!empty($sharedData[$key]) && $sharedData[$key]['expiry'] >= time()) {
    10601079            return "{$fileKey}-{$key}";
    10611080        }
     
    10671086        ];
    10681087        // Save entire sharedData list
    1069         $this->saveSharedData( $fileKey, $sharedData );
     1088        $this->saveSharedData($fileKey, $sharedData);
    10701089        return "{$fileKey}-{$key}";
    10711090    }
    10721091
    1073     public function getDownloadKey( $fileKey, $options = [] ) {
     1092    public function getDownloadKey($fileKey, $options = [])
     1093    {
    10741094        $defaults = [
    10751095            'expireIn' => 3600,
     
    10771097            'limit'    => 0,
    10781098        ];
    1079         $options = wp_parse_args( $options, $defaults );
    1080         $expireIn = intval( $options['expireIn'] );
    1081         $password = sanitize_text_field( $options['password'] ?? null );
    1082         $limit = intval( $options['limit'] );
    1083         $expiry = ( $expireIn > 0 ? time() + $expireIn : 0 );
    1084         $passwordHash = ( !empty( $password ) ? md5( $password ) : '' );
    1085         $downloadData = $this->getDownloadData( $fileKey );
    1086         $key = md5( "{$fileKey}|{$expiry}|{$passwordHash}|{$limit}" );
    1087         if ( !empty( $downloadData[$key] ) && $downloadData[$key]['expiry'] >= time() ) {
     1099        $options = wp_parse_args($options, $defaults);
     1100        $expireIn = intval($options['expireIn']);
     1101        $password = sanitize_text_field($options['password'] ?? null);
     1102        $limit = intval($options['limit']);
     1103        $expiry = ($expireIn > 0 ? time() + $expireIn : 0);
     1104        $passwordHash = (!empty($password) ? md5($password) : '');
     1105        $downloadData = $this->getDownloadData($fileKey);
     1106        $key = md5("{$fileKey}|{$expiry}|{$passwordHash}|{$limit}");
     1107        if (!empty($downloadData[$key]) && $downloadData[$key]['expiry'] >= time()) {
    10881108            return "{$fileKey}-{$key}";
    10891109        }
     
    10961116        ];
    10971117        // Save entire sharedData list
    1098         $this->saveDownloadData( $fileKey, $downloadData );
     1118        $this->saveDownloadData($fileKey, $downloadData);
    10991119        return "{$fileKey}-{$key}";
    11001120    }
    11011121
    1102     public function validateSharedLink( $combinedKey, $password = '' ) {
    1103         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1104         if ( !$fileKey || !$linkKey ) {
    1105             return false;
    1106         }
    1107         $sharedData = $this->getSharedData( $fileKey );
    1108         if ( empty( $sharedData[$linkKey] ) ) {
     1122    public function validateSharedLink($combinedKey, $password = '')
     1123    {
     1124        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1125        if (!$fileKey || !$linkKey) {
     1126            return false;
     1127        }
     1128        $sharedData = $this->getSharedData($fileKey);
     1129        if (empty($sharedData[$linkKey])) {
    11091130            return false;
    11101131        }
    11111132        $shareInfo = $sharedData[$linkKey];
    1112         if ( $shareInfo['expiry'] < time() && $shareInfo['expiry'] != 0 ) {
    1113             $this->deleteSharedEntry( $fileKey, $linkKey );
    1114             return false;
    1115         }
    1116         $hashedPassword = md5( sanitize_text_field( $password ) );
    1117         if ( !empty( $shareInfo['password'] ) ) {
    1118             if ( empty( $password ) ) {
    1119                 return new WP_Error('password_required', __( 'This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox' ));
    1120             }
    1121             if ( $shareInfo['password'] !== $hashedPassword ) {
    1122                 return new WP_Error('invalid_password', __( 'The provided password is incorrect.', 'integrate-dropbox' ));
    1123             }
    1124         }
    1125         $shareInfo['viewCount'] = intval( $shareInfo['viewCount'] ?? 0 ) + 1;
    1126         $shareInfo['lastViewed'] = current_time( 'mysql' );
    1127         $result = $this->updateSharedData( $combinedKey, $shareInfo );
    1128         if ( is_wp_error( $result ) ) {
     1133        if ($shareInfo['expiry'] < time() && $shareInfo['expiry'] != 0) {
     1134            $this->deleteSharedEntry($fileKey, $linkKey);
     1135            return false;
     1136        }
     1137        $hashedPassword = md5(sanitize_text_field($password));
     1138        if (!empty($shareInfo['password'])) {
     1139            if (empty($password)) {
     1140                return new WP_Error('password_required', __('This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox'));
     1141            }
     1142            if ($shareInfo['password'] !== $hashedPassword) {
     1143                return new WP_Error('invalid_password', __('The provided password is incorrect.', 'integrate-dropbox'));
     1144            }
     1145        }
     1146        $shareInfo['viewCount'] = intval($shareInfo['viewCount'] ?? 0) + 1;
     1147        $shareInfo['lastViewed'] = current_time('mysql');
     1148        $result = $this->updateSharedData($combinedKey, $shareInfo);
     1149        if (is_wp_error($result)) {
    11291150            return false;
    11301151        }
     
    11321153    }
    11331154
    1134     public function validateDownloadLink( $combinedKey, $password = '' ) {
    1135         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1136         if ( !$fileKey || !$linkKey ) {
    1137             return false;
    1138         }
    1139         $downloadData = $this->getDownloadData( $fileKey );
    1140         if ( empty( $downloadData[$linkKey] ) ) {
     1155    public function validateDownloadLink($combinedKey, $password = '')
     1156    {
     1157        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1158        if (!$fileKey || !$linkKey) {
     1159            return false;
     1160        }
     1161        $downloadData = $this->getDownloadData($fileKey);
     1162        if (empty($downloadData[$linkKey])) {
    11411163            return false;
    11421164        }
    11431165        $downloadInfo = $downloadData[$linkKey];
    1144         if ( $downloadInfo['expiry'] < time() && $downloadInfo['expiry'] != 0 ) {
    1145             $this->deleteDownloadEntry( $fileKey, $linkKey );
    1146             return false;
    1147         }
    1148         $downloadLimit = intval( $downloadInfo['limit'] ?? 0 );
    1149         if ( $downloadLimit > 0 && intval( $downloadInfo['downloadCount'] ?? 0 ) >= $downloadLimit ) {
    1150             $this->deleteDownloadEntry( $fileKey, $linkKey );
    1151             return new WP_Error('download_limit_exceeded', __( 'The download limit for this link has been exceeded.', 'integrate-dropbox' ));
    1152         }
    1153         $hashedPassword = md5( sanitize_text_field( $password ) );
    1154         if ( !empty( $downloadInfo['password'] ) ) {
    1155             if ( empty( $password ) ) {
    1156                 return new WP_Error('password_required', __( 'This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox' ));
    1157             }
    1158             if ( $downloadInfo['password'] !== $hashedPassword ) {
    1159                 return new WP_Error('invalid_password', __( 'The provided password is incorrect.', 'integrate-dropbox' ));
    1160             }
    1161         }
    1162         $downloadInfo['downloadCount'] = intval( $downloadInfo['downloadCount'] ?? 0 ) + 1;
    1163         $downloadInfo['lastViewed'] = current_time( 'mysql' );
    1164         $result = $this->updateDownloadData( $combinedKey, $downloadInfo );
    1165         if ( is_wp_error( $result ) ) {
     1166        if ($downloadInfo['expiry'] < time() && $downloadInfo['expiry'] != 0) {
     1167            $this->deleteDownloadEntry($fileKey, $linkKey);
     1168            return false;
     1169        }
     1170        $downloadLimit = intval($downloadInfo['limit'] ?? 0);
     1171        if ($downloadLimit > 0 && intval($downloadInfo['downloadCount'] ?? 0) >= $downloadLimit) {
     1172            $this->deleteDownloadEntry($fileKey, $linkKey);
     1173            return new WP_Error('download_limit_exceeded', __('The download limit for this link has been exceeded.', 'integrate-dropbox'));
     1174        }
     1175        $hashedPassword = md5(sanitize_text_field($password));
     1176        if (!empty($downloadInfo['password'])) {
     1177            if (empty($password)) {
     1178                return new WP_Error('password_required', __('This shared link is protected by a password. Please provide the password to access the file.', 'integrate-dropbox'));
     1179            }
     1180            if ($downloadInfo['password'] !== $hashedPassword) {
     1181                return new WP_Error('invalid_password', __('The provided password is incorrect.', 'integrate-dropbox'));
     1182            }
     1183        }
     1184        $downloadInfo['downloadCount'] = intval($downloadInfo['downloadCount'] ?? 0) + 1;
     1185        $downloadInfo['lastViewed'] = current_time('mysql');
     1186        $result = $this->updateDownloadData($combinedKey, $downloadInfo);
     1187        if (is_wp_error($result)) {
    11661188            return false;
    11671189        }
     
    11701192
    11711193    /* ================= PRIVATE ================= */
    1172     private function parseCombinedKey( $sharedKey ) {
    1173         $parts = explode( '-', $sharedKey, 2 );
     1194    private function parseCombinedKey($sharedKey)
     1195    {
     1196        $parts = explode('-', $sharedKey, 2);
    11741197        return [$parts[0] ?? '', $parts[1] ?? ''];
    11751198    }
    11761199
    1177     private function getSharedData( $fileKey ) {
    1178         global $wpdb;
    1179         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1180         if ( !$file ) {
     1200    private function getSharedData($fileKey)
     1201    {
     1202        global $wpdb;
     1203        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1204        if (!$file) {
    11811205            return [];
    11821206        }
    1183         $metaData = maybe_unserialize( $file->metaData );
     1207        $metaData = maybe_unserialize($file->metaData);
    11841208        return $metaData['sharedData'] ?? [];
    11851209    }
    11861210
    1187     private function getDownloadData( $fileKey ) {
    1188         global $wpdb;
    1189         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1190         if ( !$file ) {
     1211    private function getDownloadData($fileKey)
     1212    {
     1213        global $wpdb;
     1214        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1215        if (!$file) {
    11911216            return [];
    11921217        }
    1193         $metaData = maybe_unserialize( $file->metaData );
     1218        $metaData = maybe_unserialize($file->metaData);
    11941219        return $metaData['downloadData'] ?? [];
    11951220    }
    11961221
    1197     private function saveSharedData( $fileKey, $sharedData ) {
    1198         global $wpdb;
    1199         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1200         if ( !$file ) {
    1201             return false;
    1202         }
    1203         $metaData = maybe_unserialize( $file->metaData ) ?? [];
     1222    private function saveSharedData($fileKey, $sharedData)
     1223    {
     1224        global $wpdb;
     1225        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1226        if (!$file) {
     1227            return false;
     1228        }
     1229        $metaData = maybe_unserialize($file->metaData) ?? [];
    12041230        $metaData['sharedData'] = $sharedData;
    12051231        return $wpdb->update(
    12061232            $this->tableName,
    12071233            [
    1208                 'metaData' => maybe_serialize( $metaData ),
     1234                'metaData' => maybe_serialize($metaData),
    12091235            ],
    12101236            [
     
    12161242    }
    12171243
    1218     private function saveDownloadData( $fileKey, $downloadData ) {
    1219         global $wpdb;
    1220         $file = $wpdb->get_row( $wpdb->prepare( "SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey ) );
    1221         if ( !$file ) {
    1222             return false;
    1223         }
    1224         $metaData = maybe_unserialize( $file->metaData ) ?? [];
     1244    private function saveDownloadData($fileKey, $downloadData)
     1245    {
     1246        global $wpdb;
     1247        $file = $wpdb->get_row($wpdb->prepare("SELECT metaData FROM %i WHERE fileKey = %s", $this->tableName, $fileKey));
     1248        if (!$file) {
     1249            return false;
     1250        }
     1251        $metaData = maybe_unserialize($file->metaData) ?? [];
    12251252        $metaData['downloadData'] = $downloadData;
    12261253        return $wpdb->update(
    12271254            $this->tableName,
    12281255            [
    1229                 'metaData' => maybe_serialize( $metaData ),
     1256                'metaData' => maybe_serialize($metaData),
    12301257            ],
    12311258            [
     
    12371264    }
    12381265
    1239     public function updateSharedData( $combinedKey, $updates = [] ) {
    1240         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1241         if ( !$fileKey || !$linkKey ) {
    1242             return false;
    1243         }
    1244         $sharedData = $this->getSharedData( $fileKey );
    1245         if ( empty( $sharedData[$linkKey] ) ) {
     1266    public function updateSharedData($combinedKey, $updates = [])
     1267    {
     1268        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1269        if (!$fileKey || !$linkKey) {
     1270            return false;
     1271        }
     1272        $sharedData = $this->getSharedData($fileKey);
     1273        if (empty($sharedData[$linkKey])) {
    12461274            return false;
    12471275        }
    12481276        // Only update provided fields
    1249         $sharedData[$linkKey] = array_merge( $sharedData[$linkKey], array_filter( $updates, function ( $v ) {
     1277        $sharedData[$linkKey] = array_merge($sharedData[$linkKey], array_filter($updates, function ($v) {
    12501278            return $v !== null;
    1251         } ) );
    1252         return $this->saveSharedData( $fileKey, $sharedData );
    1253     }
    1254 
    1255     public function updateDownloadData( $combinedKey, $updates = [] ) {
    1256         [$fileKey, $linkKey] = $this->parseCombinedKey( $combinedKey );
    1257         if ( !$fileKey || !$linkKey ) {
    1258             return false;
    1259         }
    1260         $downloadData = $this->getDownloadData( $fileKey );
    1261         if ( empty( $downloadData[$linkKey] ) ) {
     1279        }));
     1280        return $this->saveSharedData($fileKey, $sharedData);
     1281    }
     1282
     1283    public function updateDownloadData($combinedKey, $updates = [])
     1284    {
     1285        [$fileKey, $linkKey] = $this->parseCombinedKey($combinedKey);
     1286        if (!$fileKey || !$linkKey) {
     1287            return false;
     1288        }
     1289        $downloadData = $this->getDownloadData($fileKey);
     1290        if (empty($downloadData[$linkKey])) {
    12621291            return false;
    12631292        }
    12641293        // Only update provided fields
    1265         $downloadData[$linkKey] = array_merge( $downloadData[$linkKey], array_filter( $updates, function ( $v ) {
     1294        $downloadData[$linkKey] = array_merge($downloadData[$linkKey], array_filter($updates, function ($v) {
    12661295            return $v !== null;
    1267         } ) );
    1268         return $this->saveDownloadData( $fileKey, $downloadData );
    1269     }
    1270 
    1271     private function deleteSharedEntry( $fileKey, $linkKey ) {
    1272         $sharedData = $this->getSharedData( $fileKey );
    1273         if ( isset( $sharedData[$linkKey] ) ) {
     1296        }));
     1297        return $this->saveDownloadData($fileKey, $downloadData);
     1298    }
     1299
     1300    private function deleteSharedEntry($fileKey, $linkKey)
     1301    {
     1302        $sharedData = $this->getSharedData($fileKey);
     1303        if (isset($sharedData[$linkKey])) {
    12741304            unset($sharedData[$linkKey]);
    1275             return $this->saveSharedData( $fileKey, $sharedData );
     1305            return $this->saveSharedData($fileKey, $sharedData);
    12761306        }
    12771307        return false;
    12781308    }
    12791309
    1280     private function deleteDownloadEntry( $fileKey, $linkKey ) {
    1281         $downloadData = $this->getDownloadData( $fileKey );
    1282         if ( isset( $downloadData[$linkKey] ) ) {
     1310    private function deleteDownloadEntry($fileKey, $linkKey)
     1311    {
     1312        $downloadData = $this->getDownloadData($fileKey);
     1313        if (isset($downloadData[$linkKey])) {
    12831314            unset($downloadData[$linkKey]);
    1284             return $this->saveDownloadData( $fileKey, $downloadData );
     1315            return $this->saveDownloadData($fileKey, $downloadData);
    12851316        }
    12861317        return false;
    12871318    }
    12881319
    1289     private function getChildFolderIds( $parentPath, $accountId ) {
    1290         if ( empty( $parentPath ) || empty( $accountId ) ) {
     1320    private function getChildFolderIds($parentPath, $accountId)
     1321    {
     1322        if (empty($parentPath) || empty($accountId)) {
    12911323            return [];
    12921324        }
    12931325        global $wpdb;
    1294         return $wpdb->get_results( $wpdb->prepare(
     1326        return $wpdb->get_results($wpdb->prepare(
    12951327            "SELECT path FROM %i WHERE parent = %s AND accountId = %s AND extension = 'folder'",
    12961328            $this->tableName,
    12971329            $parentPath,
    12981330            $accountId
    1299         ), ARRAY_A );
    1300     }
    1301 
    1302     private function processFiles( $files, $returnType = 'array', $filter = null ) {
     1331        ), ARRAY_A);
     1332    }
     1333
     1334    private function processFiles($files, $returnType = 'array', $filter = null)
     1335    {
    13031336        $processedFiles = [];
    1304         foreach ( $files as $file ) {
    1305             $processedFiles[] = $this->processFile( $file, $returnType, $filter );
     1337        foreach ($files as $file) {
     1338            $processedFiles[] = $this->processFile($file, $returnType, $filter);
    13061339        }
    13071340        return $processedFiles;
    13081341    }
    13091342
    1310     private function processFile( $file, $returnType = 'object', $filter = null ) {
    1311         if ( empty( $file ) ) {
     1343    private function processFile($file, $returnType = 'object', $filter = null)
     1344    {
     1345        if (empty($file)) {
    13121346            return [];
    13131347        }
     
    13271361            'sharedLink'      => $file->sharedLink,
    13281362            'isDir'           => $file->isDir,
    1329             'permissions'     => maybe_unserialize( $file->permissions ),
     1363            'permissions'     => maybe_unserialize($file->permissions),
    13301364            'hasOwnThumbnail' => $file->hasOwnThumbnail,
    13311365            'icon'            => $file->icon,
    1332             'additionalData'  => maybe_unserialize( $file->additionalData ),
    1333             'metaData'        => maybe_unserialize( $file->metaData ),
     1366            'additionalData'  => maybe_unserialize($file->additionalData),
     1367            'metaData'        => maybe_unserialize($file->metaData),
    13341368            'createdAt'       => $file->createdAt,
    13351369            'updatedAt'       => $file->updatedAt,
    13361370        ];
    1337         if ( $returnType === 'object' ) {
     1371        if ($returnType === 'object') {
    13381372            return new File($fileData);
    1339         } elseif ( $returnType === 'array' ) {
     1373        } elseif ($returnType === 'array') {
    13401374            return $fileData;
    13411375        }
     
    13461380            'mimeType'   => $file->mimeType,
    13471381            'size'       => $file->size,
    1348             'thumbnails' => maybe_unserialize( $file->thumbnails ),
    1349         ];
    1350     }
    1351 
    1352     private function processExtensions( array $extensions, array $additionalExtensions, string $filterType ) : array {
    1353         if ( empty( $additionalExtensions ) ) {
     1382            'thumbnails' => maybe_unserialize($file->thumbnails),
     1383        ];
     1384    }
     1385
     1386    private function processExtensions(array $extensions, array $additionalExtensions, string $filterType): array
     1387    {
     1388        if (empty($additionalExtensions)) {
    13541389            return $extensions;
    13551390        }
    1356         if ( empty( $extensions ) ) {
     1391        if (empty($extensions)) {
    13571392            return $additionalExtensions;
    13581393        }
    1359         if ( $filterType === 'include' ) {
    1360             $filterExtensions = array_filter( $extensions, function ( $ext ) use($additionalExtensions) {
    1361                 return in_array( $ext, $additionalExtensions );
    1362             } );
    1363             return array_values( $filterExtensions );
    1364         } elseif ( $filterType === 'exclude' ) {
    1365             $filterExtensions = array_filter( $extensions, fn( $ext ) => !in_array( $ext, $additionalExtensions ) );
    1366             return array_values( $filterExtensions );
     1394        if ($filterType === 'include') {
     1395            $filterExtensions = array_filter($extensions, function ($ext) use ($additionalExtensions) {
     1396                return in_array($ext, $additionalExtensions);
     1397            });
     1398            return array_values($filterExtensions);
     1399        } elseif ($filterType === 'exclude') {
     1400            $filterExtensions = array_filter($extensions, fn ($ext) => !in_array($ext, $additionalExtensions));
     1401            return array_values($filterExtensions);
    13671402        }
    13681403        return $extensions;
    13691404    }
    13701405
    1371     private function processFolderTree( array $items, array $rootPaths ) {
     1406    private function processFolderTree(array $items, array $rootPaths)
     1407    {
    13721408        $tree = [];
    13731409        $lookup = [];
    1374         foreach ( $items as $item ) {
    1375             $path = rtrim( $item['path'], '/' );
     1410        foreach ($items as $item) {
     1411            $path = rtrim($item['path'], '/');
    13761412            $lookup[$path] = [
    13771413                'name'     => $item['name'],
     
    13791415                'children' => [],
    13801416                'path'     => $path,
    1381                 'parent'   => rtrim( $item['parent'], '/' ),
     1417                'parent'   => rtrim($item['parent'], '/'),
    13821418            ];
    13831419        }
    1384         foreach ( $lookup as $path => &$node ) {
    1385             if ( in_array( $node['path'], $rootPaths, true ) || $node['parent'] === '' || $node['parent'] === '/' ) {
     1420        foreach ($lookup as $path => &$node) {
     1421            if (in_array($node['path'], $rootPaths, true) || $node['parent'] === '' || $node['parent'] === '/') {
    13861422                unset($node['parent']);
    1387                 $tree[] =& $node;
     1423                $tree[] = & $node;
    13881424            } else {
    1389                 if ( isset( $lookup[$node['parent']] ) ) {
    1390                     $lookup[$node['parent']]['children'][] =& $node;
     1425                if (isset($lookup[$node['parent']])) {
     1426                    $lookup[$node['parent']]['children'][] = & $node;
    13911427                }
    13921428            }
     
    14021438        //     }
    14031439        // }
    1404         $tree = array_map( function ( $item ) {
    1405             if ( empty( $item['children'] ) ) {
     1440        $tree = array_map(function ($item) {
     1441            if (empty($item['children'])) {
    14061442                unset($item['children']);
    14071443            }
    14081444            return $item;
    1409         }, $tree );
    1410         return array_values( $tree );
     1445        }, $tree);
     1446        return array_values($tree);
    14111447    }
    14121448
Note: See TracChangeset for help on using the changeset viewer.