Skip to content

Commit

Permalink
Merge pull request #80 from Bearsampp/ram
Browse files Browse the repository at this point in the history
% progressbar
  • Loading branch information
jwaisner authored Aug 29, 2024
2 parents e5d1e93 + 6637678 commit 995a333
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 91 deletions.
106 changes: 52 additions & 54 deletions core/classes/actions/class.action.quickPick.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?php
/*
* Copyright (c) 2021-2024 Bearsampp
* License: GNU General Public License version 3 or later; see LICENSE.txt
* Author: Bear
* Website: https://bearsampp.com
* Github: https://github.com/Bearsampp
*
* * Copyright (c) 2021-2024 Bearsampp
* * License: GNU General Public License version 3 or later; see LICENSE.txt
* * Website: https://bearsampp.com
* * Github: https://github.com/Bearsampp
*
*/

/**
Expand Down Expand Up @@ -405,73 +406,70 @@ public function installModule(string $module, string $version): array
* @return array An array containing the status and message.
*/
public function fetchAndUnzipModule(string $moduleUrl, string $module): array
{
Util::logDebug( "$module is: " . $module );
{
Util::logDebug("$module is: " . $module);

global $bearsamppRoot, $bearsamppCore;
$tmpDir = $bearsamppRoot->getTmpPath();
Util::logDebug( 'Temporary Directory: ' . $tmpDir );
global $bearsamppRoot, $bearsamppCore;
$tmpDir = $bearsamppRoot->getTmpPath();
Util::logDebug('Temporary Directory: ' . $tmpDir);

$fileName = basename( $moduleUrl );
Util::logDebug( 'File Name: ' . $fileName );
$fileName = basename($moduleUrl);
Util::logDebug('File Name: ' . $fileName);

$tmpFilePath = $tmpDir . '/' . $fileName;
Util::logDebug( 'File Path: ' . $tmpFilePath );
$tmpFilePath = $tmpDir . '/' . $fileName;
Util::logDebug('File Path: ' . $tmpFilePath);

$moduleName = str_replace( 'module-', '', $module );
Util::logDebug( 'Module Name: ' . $moduleName );
$moduleName = str_replace('module-', '', $module);
Util::logDebug('Module Name: ' . $moduleName);

$moduleType = $this->modules[$module]['type'];
Util::logDebug( 'Module Type: ' . $moduleType );
$moduleType = $this->modules[$module]['type'];
Util::logDebug('Module Type: ' . $moduleType);

// Get module type
$destination = $this->getModuleDestinationPath( $moduleType, $moduleName );
Util::logDebug( 'Destination: ' . $destination );
// Get module type
$destination = $this->getModuleDestinationPath($moduleType, $moduleName);
Util::logDebug('Destination: ' . $destination);

// Retrieve the file path from the URL using the bearsamppCore module,
// passing the module URL and temporary file path, with the use Progress Bar parameter set to true.
$result = $bearsamppCore->getFileFromUrl( $moduleUrl, $tmpFilePath, true );
// Retrieve the file path from the URL using the bearsamppCore module,
// passing the module URL and temporary file path, with the use Progress Bar parameter set to true.
$result = $bearsamppCore->getFileFromUrl($moduleUrl, $tmpFilePath, true);

// Check if $result is false
if ( $result === false ) {
Util::logError( 'Failed to retrieve file from URL: ' . $moduleUrl );
// Check if $result is false
if ($result === false) {
Util::logError('Failed to retrieve file from URL: ' . $moduleUrl);
return ['error' => 'Failed to retrieve file from URL'];
}

return ['error' => 'Failed to retrieve file from URL'];
}
// Determine the file extension and call the appropriate unzipping function
$fileExtension = pathinfo($tmpFilePath, PATHINFO_EXTENSION);
Util::logDebug('File extension: ' . $fileExtension);

// Determine the file extension and call the appropriate unzipping function
$fileExtension = pathinfo( $tmpFilePath, PATHINFO_EXTENSION );
Util::logDebug( 'File extension: ' . $fileExtension );
if ($fileExtension === '7z' || $fileExtension === 'zip') {
// Send phase indicator for extraction
echo json_encode(['phase' => 'extracting']);
if (ob_get_length()) {
ob_flush();
}
flush();

if ( $fileExtension === '7z' || $fileExtension === 'zip' ) {
// Send phase indicator for extraction
echo json_encode( ['phase' => 'extracting'] );
if ( ob_get_length() ) {
$unzipResult = $bearsamppCore->unzipFile($tmpFilePath, $destination, function ($currentPercentage) {
echo json_encode(['progress' => "$currentPercentage%"]);
if (ob_get_length()) {
ob_flush();
}
flush();
});

$unzipResult = $bearsamppCore->unzipFile( $tmpFilePath, $destination, function ($currentFile, $totalFiles) {
echo json_encode( ['progress' => "$currentFile of $totalFiles"] );
if ( ob_get_length() ) {
ob_flush();
}
flush();
} );

if ( $unzipResult === false ) {
return ['error' => 'Failed to unzip file. File: ' . $tmpFilePath . ' could not be unzipped', 'Destination: ' . $destination];
}
}
else {
Util::logError( 'Unsupported file extension: ' . $fileExtension );

return ['error' => 'Unsupported file extension'];
if ($unzipResult === false) {
return ['error' => 'Failed to unzip file. File: ' . $tmpFilePath . ' could not be unzipped', 'Destination: ' . $destination];
}

return ['success' => 'Module installed successfully'];
} else {
Util::logError('Unsupported file extension: ' . $fileExtension);
return ['error' => 'Unsupported file extension'];
}

return ['success' => 'Module installed successfully'];
}

/**
* Get the destination path for a given module type and name.
*
Expand Down
103 changes: 73 additions & 30 deletions core/classes/class.core.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<?php
/*
* Copyright (c) 2021-2024 Bearsampp
* License: GNU General Public License version 3 or later; see LICENSE.txt
* Author: Bear
* Website: https://bearsampp.com
* Github: https://github.com/Bearsampp
*
* * Copyright (c) 2021-2024 Bearsampp
* * License: GNU General Public License version 3 or later; see LICENSE.txt
* * Website: https://bearsampp.com
* * Github: https://github.com/Bearsampp
*
*/

/**
Expand Down Expand Up @@ -458,7 +459,7 @@ public function __toString()
return 'core object';
}

/**
/**
* Unzips a file to the specified directory and provides progress updates.
*
* This method uses the 7-Zip command-line tool to extract the contents of a zip file.
Expand All @@ -471,9 +472,12 @@ public function __toString()
* - int $currentFile: The current file number being extracted.
* - int $totalFiles: The total number of files to be extracted.
*
* @return array An array containing the result of the extraction:
* - 'success' => true and 'numFiles' => int on success.
* - 'error' => string and 'numFiles' => int on failure.
* @global object $bearsamppRoot Global object to get core paths.
*
* @return array|false An array containing the result of the extraction on success or failure:
* - On success: ['success' => true, 'numFiles' => int]
* - On failure: ['error' => string, 'numFiles' => int]
* - Returns false if the 7-Zip executable is not found.
*/
public function unzipFile($filePath, $destination, $progressCallback = null)
{
Expand All @@ -494,41 +498,80 @@ public function unzipFile($filePath, $destination, $progressCallback = null)
// Extract the number of files from the test command output
preg_match( '/Files: (\d+)/', $testOutput, $matches );
$numFiles = isset( $matches[1] ) ? (int) $matches[1] : 0;
Util::logDebug( 'Number of files to be extracted: ' . $numFiles );
Util::logTrace( 'Number of files to be extracted: ' . $numFiles );

// Command to extract the archive
$command = escapeshellarg( $sevenZipPath ) . ' x ' . escapeshellarg( $filePath ) . ' -y -bb1 -o' . escapeshellarg( $destination );
$command = escapeshellarg( $sevenZipPath ) . ' x ' . escapeshellarg( $filePath ) . ' -y -bsp1 -bb0 -o' . escapeshellarg( $destination );
Util::logTrace( 'Executing command: ' . $command );

$process = popen( $command, 'rb' );

if ( $process ) {
$filesExtracted = 0;
$buffer = '';

$buffer = '';
while ( !feof( $process ) ) {
$buffer .= fread( $process, 8192 ); // Read in smaller chunks of 4KB

while ( ($newlinePos = strpos( $buffer, "\n" )) !== false ) {
$line = substr( $buffer, 0, $newlinePos + 1 );
$buffer = substr( $buffer, $newlinePos + 1 );

if ( $progressCallback && preg_match( '/^- (.+)$/', $line, $matches ) ) {
$fileName = trim( $matches[1] );

// Check if the extracted item is a file and not a directory
if ( substr( $fileName, -1 ) !== '\\' ) {
$filesExtracted++;
if ( $filesExtracted <= $numFiles ) {
call_user_func( $progressCallback, $filesExtracted, $numFiles );
}
$buffer .= fread( $process, 8192 ); // Read in chunks of 8KB
while ( ($pos = strpos( $buffer, "\r" )) !== false ) {
$line = substr( $buffer, 0, $pos );
$buffer = substr( $buffer, $pos + 1 );
$line = trim( $line ); // Remove any leading/trailing whitespace
Util::logTrace( "Processing line: $line" );

// Check if the line indicates everything is okay
if ( $line === "Everything is Ok" ) {
if ( $progressCallback ) {
Util::logTrace( "Extraction progress: 100%" );
call_user_func( $progressCallback, 100 );
Util::logTrace( "Progress callback called with percentage: 100" );
}
}
else if ( $progressCallback && preg_match( '/(?:^|\s)(\d+)%/', $line, $matches ) ) {
$currentPercentage = intval( $matches[1] );
Util::logTrace( "Extraction progress: $currentPercentage%" );
call_user_func( $progressCallback, $currentPercentage );
Util::logTrace( "Progress callback called with percentage: $currentPercentage" );
}
else {
Util::logTrace( "Line did not match pattern: $line" );
}
}
}

// Process any remaining data in the buffer
if ( !empty( $buffer ) ) {
$line = trim( $buffer );
Util::logTrace( "Processing remaining line: $line" );

// Check if the remaining line indicates everything is okay
if ( $line === "Everything is Ok" ) {
if ( $progressCallback ) {
Util::logTrace( "Extraction progress: 100%" );
call_user_func( $progressCallback, 100 );
Util::logTrace( "Progress callback called with percentage: 100" );
}
}
else if ( $progressCallback && preg_match( '/(?:^|\s)(\d+)%/', $line, $matches ) ) {
$currentPercentage = intval( $matches[1] );
Util::logTrace( "Extraction progress: $currentPercentage%" );
call_user_func( $progressCallback, $currentPercentage );
Util::logTrace( "Progress callback called with percentage: $currentPercentage" );
}
else {
Util::logTrace( "Remaining line did not match pattern: $line" );
}
}

$returnVar = pclose( $process );
Util::logDebug( 'Command return value: ' . $returnVar );
Util::logTrace( 'Command return value: ' . $returnVar );

// Set progress to 100% if the command was successful
if ( $returnVar === 0 && $progressCallback ) {
Util::logTrace( "Extraction completed successfully. Setting progress to 100%" );
call_user_func( $progressCallback, 100 );
Util::logTrace( "Progress callback called with percentage: 100" );

// Adding a small delay to ensure the progress bar update is processed
usleep( 100000 ); // 100 milliseconds
}

if ( $returnVar === 0 ) {
Util::logDebug( 'Successfully unzipped file to: ' . $destination );
Expand Down
21 changes: 14 additions & 7 deletions core/resources/homepage/js/quickpick.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
*
* * Copyright (c) 2021-2024 Bearsampp
* * License: GNU General Public License version 3 or later; see LICENSE.txt
* * Website: https://bearsampp.com
* * Github: https://github.com/Bearsampp
*
*/

/**
* Initializes event listeners and handles the UI interactions for the custom select dropdown.
* This function is executed when the DOM content is fully loaded.
Expand Down Expand Up @@ -117,6 +126,7 @@ function hideall() {
*
* @param {string} moduleName - The name of the module to install.
* @param {string} version - The version of the module to install.
* @returns {Promise<void>} - A promise that resolves when the installation is complete.
*/
async function installModule(moduleName, version) {
const url = AJAX_URL;
Expand Down Expand Up @@ -174,19 +184,14 @@ async function installModule(moduleName, version) {
const progressValue = data.progress;
progressbar.style.width = '100%';
if (isDownloading) {
progressbar.setAttribute('aria-valuenow', progressValue);
progressbar.innerText = `${progressValue} KBytes Downloaded`;
} else {
progressbar.setAttribute('aria-valuenow', progressValue);
progressbar.innerText = `${progressValue} Extracted`;
}
} else if (data.success) {

console.log(data);
isCompleted = true;
messageData = data.message;
// window.alert(data.message);

} else if (data.error) {
console.error('Error:', data.error);
window.alert(`Error: ${data.error}`);
Expand All @@ -197,13 +202,15 @@ async function installModule(moduleName, version) {
// Ignore JSON parse errors for incomplete parts
}
}

// Clear responseText to keep only the unprocessed part
responseText = parts[parts.length - 1].startsWith('{') ? parts[parts.length - 1] : '';
}
} catch (error) {
console.error('Failed to install module:', error);
window.alert('Failed to install module: ' + error.message);
} finally {
if (isCompleted === true)
{
if (isCompleted === true) {
confirm(messageData);
}
setTimeout(() => {
Expand Down

0 comments on commit 995a333

Please sign in to comment.