build-update.ps1 was reading SQL migrations line-by-line, causing multi-line CREATE TABLE/INSERT statements to be stored as fragments in manifests. Fixed to strip comments, join lines, and split by semicolons. Fixed ver_0.324_manifest.json with correct SQL statements. Added try-catch in UpdateRepository to prevent fatal crashes on SQL errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
605 lines
21 KiB
PHP
605 lines
21 KiB
PHP
<?php
|
|
namespace Domain\Update;
|
|
|
|
class UpdateRepository
|
|
{
|
|
private $db;
|
|
|
|
public function __construct( $db )
|
|
{
|
|
$this->db = $db;
|
|
}
|
|
|
|
/**
|
|
* Wykonuje aktualizację do następnej wersji.
|
|
*
|
|
* @return array{success: bool, log: array, no_updates?: bool}
|
|
*/
|
|
public function update(): array
|
|
{
|
|
global $settings;
|
|
|
|
@file_put_contents( '../libraries/update_log.txt', '' );
|
|
|
|
$log = [];
|
|
$log[] = '[START] Rozpoczęcie aktualizacji - ' . date( 'Y-m-d H:i:s' );
|
|
$log[] = '[INFO] Aktualna wersja: ' . \Shared\Helpers\Helpers::get_version();
|
|
|
|
\Shared\Helpers\Helpers::delete_session( 'new-version' );
|
|
|
|
$versionsUrl = 'https://shoppro.project-dc.pl/updates/versions.php?key=' . $settings['update_key'];
|
|
$versions = @file_get_contents( $versionsUrl );
|
|
|
|
if ( $versions === false ) {
|
|
$log[] = '[ERROR] Nie udało się pobrać listy wersji z: ' . $versionsUrl;
|
|
$this->saveLog( $log );
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$log[] = '[OK] Pobrano listę wersji';
|
|
$versions = explode( PHP_EOL, $versions );
|
|
$log[] = '[INFO] Znaleziono ' . count( $versions ) . ' wersji do sprawdzenia';
|
|
|
|
foreach ( $versions as $ver ) {
|
|
$ver = trim( $ver );
|
|
if ( floatval( $ver ) <= (float) \Shared\Helpers\Helpers::get_version() ) {
|
|
continue;
|
|
}
|
|
|
|
$log[] = '[INFO] Aktualizacja do wersji: ' . $ver;
|
|
$dir = strlen( $ver ) == 5
|
|
? substr( $ver, 0, strlen( $ver ) - 2 ) . '0'
|
|
: substr( $ver, 0, strlen( $ver ) - 1 ) . '0';
|
|
|
|
$result = $this->downloadAndApply( $ver, $dir, $log );
|
|
$this->saveLog( $result['log'] );
|
|
return $result;
|
|
}
|
|
|
|
$log[] = '[INFO] Brak nowych wersji do zainstalowania';
|
|
$this->saveLog( $log );
|
|
return [ 'success' => true, 'log' => $log, 'no_updates' => true ];
|
|
}
|
|
|
|
/**
|
|
* Dispatcher — próbuje pobrać manifest, jeśli jest → nowa ścieżka, jeśli brak → legacy.
|
|
*/
|
|
private function downloadAndApply( string $ver, string $dir, array $log ): array
|
|
{
|
|
$baseUrl = 'https://shoppro.project-dc.pl/updates/' . $dir;
|
|
|
|
$manifest = $this->downloadManifest( $baseUrl, $ver );
|
|
|
|
if ( $manifest !== null ) {
|
|
$log[] = '[INFO] Znaleziono manifest dla wersji ' . $ver;
|
|
return $this->downloadAndApplyWithManifest( $ver, $dir, $manifest, $log );
|
|
}
|
|
|
|
$log[] = '[INFO] Brak manifestu, używam trybu legacy';
|
|
return $this->downloadAndApplyLegacy( $ver, $dir, $log );
|
|
}
|
|
|
|
/**
|
|
* Pobiera manifest JSON dla danej wersji.
|
|
*
|
|
* @return array|null Zdekodowany manifest lub null jeśli brak
|
|
*/
|
|
private function downloadManifest( string $baseUrl, string $ver )
|
|
{
|
|
$manifestUrl = $baseUrl . '/ver_' . $ver . '_manifest.json';
|
|
|
|
$ch = curl_init( $manifestUrl );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
curl_setopt( $ch, CURLOPT_HEADER, false );
|
|
curl_setopt( $ch, CURLOPT_TIMEOUT, 15 );
|
|
$response = curl_exec( $ch );
|
|
$httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
|
|
curl_close( $ch );
|
|
|
|
if ( !$response || $httpCode !== 200 ) {
|
|
return null;
|
|
}
|
|
|
|
$manifest = json_decode( $response, true );
|
|
if ( !is_array( $manifest ) || !isset( $manifest['version'] ) ) {
|
|
return null;
|
|
}
|
|
|
|
return $manifest;
|
|
}
|
|
|
|
/**
|
|
* Aktualizacja z użyciem manifestu — checksum, backup, SQL z manifestu, usuwanie z manifestu.
|
|
*/
|
|
private function downloadAndApplyWithManifest( string $ver, string $dir, array $manifest, array $log ): array
|
|
{
|
|
$baseUrl = 'https://shoppro.project-dc.pl/updates/' . $dir;
|
|
|
|
$log[] = '[INFO] Tryb aktualizacji: manifest';
|
|
|
|
// 1. Pobieranie ZIP
|
|
$zipUrl = $baseUrl . '/ver_' . $ver . '.zip';
|
|
$log[] = '[INFO] Pobieranie pliku ZIP: ' . $zipUrl;
|
|
$file = @file_get_contents( $zipUrl );
|
|
|
|
if ( $file === false ) {
|
|
$log[] = '[ERROR] Nie udało się pobrać pliku ZIP';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$fileSize = strlen( $file );
|
|
$log[] = '[OK] Pobrano plik ZIP, rozmiar: ' . $fileSize . ' bajtów';
|
|
|
|
if ( $fileSize < 100 ) {
|
|
$log[] = '[ERROR] Plik ZIP jest za mały (prawdopodobnie błąd pobierania)';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$dlHandler = @fopen( 'update.zip', 'w' );
|
|
if ( !$dlHandler ) {
|
|
$log[] = '[ERROR] Nie udało się otworzyć pliku update.zip do zapisu';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
$written = fwrite( $dlHandler, $file );
|
|
fclose( $dlHandler );
|
|
|
|
if ( $written === false || $written === 0 ) {
|
|
$log[] = '[ERROR] Nie udało się zapisać pliku ZIP';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$log[] = '[OK] Zapisano plik ZIP (' . $written . ' bajtów)';
|
|
|
|
// 2. Weryfikacja checksum
|
|
if ( isset( $manifest['checksum_zip'] ) ) {
|
|
$checksumResult = $this->verifyChecksum( 'update.zip', $manifest['checksum_zip'], $log );
|
|
$log = $checksumResult['log'];
|
|
|
|
if ( !$checksumResult['valid'] ) {
|
|
@unlink( 'update.zip' );
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
}
|
|
|
|
// 3. Backup plików przed nadpisaniem
|
|
$log = $this->createBackup( $manifest, $log );
|
|
|
|
// 4. SQL z manifestu
|
|
if ( !empty( $manifest['sql'] ) ) {
|
|
$log[] = '[INFO] Wykonywanie zapytań SQL z manifestu (' . count( $manifest['sql'] ) . ')';
|
|
$success = 0;
|
|
$errors = 0;
|
|
|
|
foreach ( $manifest['sql'] as $query ) {
|
|
$query = trim( $query );
|
|
if ( $query === '' || strpos( $query, '--' ) === 0 ) {
|
|
continue;
|
|
}
|
|
try {
|
|
if ( $this->db->query( $query ) ) {
|
|
$success++;
|
|
} else {
|
|
$errors++;
|
|
$log[] = '[WARNING] Błąd SQL: ' . $query;
|
|
}
|
|
} catch ( \Exception $e ) {
|
|
$errors++;
|
|
$log[] = '[WARNING] Wyjątek SQL: ' . $e->getMessage() . ' | Query: ' . substr( $query, 0, 200 );
|
|
}
|
|
}
|
|
|
|
$log[] = '[INFO] Wykonano zapytania SQL - sukces: ' . $success . ', błędy: ' . $errors;
|
|
}
|
|
|
|
// 5. Usuwanie plików z manifestu
|
|
if ( !empty( $manifest['files']['deleted'] ) ) {
|
|
$deletedCount = 0;
|
|
foreach ( $manifest['files']['deleted'] as $relativePath ) {
|
|
$fullPath = '../' . $relativePath;
|
|
if ( file_exists( $fullPath ) ) {
|
|
if ( @unlink( $fullPath ) ) {
|
|
$deletedCount++;
|
|
} else {
|
|
$log[] = '[WARNING] Nie udało się usunąć pliku: ' . $fullPath;
|
|
}
|
|
}
|
|
}
|
|
$log[] = '[INFO] Usunięto plików: ' . $deletedCount;
|
|
}
|
|
|
|
// 6. Usuwanie katalogów z manifestu
|
|
if ( !empty( $manifest['directories_deleted'] ) ) {
|
|
$deletedDirs = 0;
|
|
foreach ( $manifest['directories_deleted'] as $dirPath ) {
|
|
$fullPath = '../' . $dirPath;
|
|
if ( is_dir( $fullPath ) ) {
|
|
\Shared\Helpers\Helpers::delete_dir( $fullPath );
|
|
$deletedDirs++;
|
|
}
|
|
}
|
|
$log[] = '[INFO] Usunięto katalogów: ' . $deletedDirs;
|
|
}
|
|
|
|
// 7. Rozpakowywanie ZIP
|
|
$log = $this->extractZip( 'update.zip', $log );
|
|
|
|
// 8. Aktualizacja wersji
|
|
$versionFile = '../libraries/version.ini';
|
|
$handle = @fopen( $versionFile, 'w' );
|
|
if ( !$handle ) {
|
|
$log[] = '[ERROR] Nie udało się otworzyć pliku version.ini do zapisu';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
fwrite( $handle, $ver );
|
|
fclose( $handle );
|
|
|
|
$log[] = '[OK] Zaktualizowano plik version.ini do wersji: ' . $ver;
|
|
$log[] = '[SUCCESS] Aktualizacja do wersji ' . $ver . ' zakończona pomyślnie';
|
|
|
|
return [ 'success' => true, 'log' => $log ];
|
|
}
|
|
|
|
/**
|
|
* Weryfikuje sumę kontrolną pliku.
|
|
*
|
|
* @param string $filePath Ścieżka do pliku
|
|
* @param string $expectedChecksum Suma w formacie "sha256:abc123..."
|
|
* @param array $log Tablica logów
|
|
* @return array{valid: bool, log: array}
|
|
*/
|
|
private function verifyChecksum( string $filePath, string $expectedChecksum, array $log ): array
|
|
{
|
|
$parts = explode( ':', $expectedChecksum, 2 );
|
|
if ( count( $parts ) !== 2 ) {
|
|
$log[] = '[ERROR] Nieprawidłowy format sumy kontrolnej: ' . $expectedChecksum;
|
|
return [ 'valid' => false, 'log' => $log ];
|
|
}
|
|
|
|
$algorithm = $parts[0];
|
|
$expected = $parts[1];
|
|
|
|
$actual = @hash_file( $algorithm, $filePath );
|
|
|
|
if ( $actual === false ) {
|
|
$log[] = '[ERROR] Nie udało się obliczyć sumy kontrolnej pliku';
|
|
return [ 'valid' => false, 'log' => $log ];
|
|
}
|
|
|
|
if ( $actual !== $expected ) {
|
|
$log[] = '[ERROR] Suma kontrolna nie zgadza się! Oczekiwano: ' . $expected . ', otrzymano: ' . $actual;
|
|
return [ 'valid' => false, 'log' => $log ];
|
|
}
|
|
|
|
$log[] = '[OK] Suma kontrolna ZIP zgodna';
|
|
return [ 'valid' => true, 'log' => $log ];
|
|
}
|
|
|
|
/**
|
|
* Tworzy kopię zapasową plików przed aktualizacją.
|
|
*
|
|
* @param array $manifest Dane z manifestu
|
|
* @param array $log Tablica logów
|
|
* @return array Zaktualizowana tablica logów
|
|
*/
|
|
private function createBackup( array $manifest, array $log ): array
|
|
{
|
|
$version = isset( $manifest['version'] ) ? $manifest['version'] : 'unknown';
|
|
$backupDir = '../backups/' . str_replace( '.', '_', $version ) . '_' . date( 'Ymd_His' );
|
|
|
|
$log[] = '[INFO] Tworzenie kopii zapasowej w: ' . $backupDir;
|
|
|
|
$projectRoot = realpath( '../' );
|
|
if ( !$projectRoot ) {
|
|
$log[] = '[WARNING] Nie udało się określić katalogu projektu, pomijam backup';
|
|
return $log;
|
|
}
|
|
|
|
$filesToBackup = [];
|
|
if ( isset( $manifest['files']['modified'] ) && is_array( $manifest['files']['modified'] ) ) {
|
|
$filesToBackup = array_merge( $filesToBackup, $manifest['files']['modified'] );
|
|
}
|
|
if ( isset( $manifest['files']['deleted'] ) && is_array( $manifest['files']['deleted'] ) ) {
|
|
$filesToBackup = array_merge( $filesToBackup, $manifest['files']['deleted'] );
|
|
}
|
|
|
|
if ( empty( $filesToBackup ) ) {
|
|
$log[] = '[INFO] Brak plików do backupu';
|
|
return $log;
|
|
}
|
|
|
|
$backedUp = 0;
|
|
foreach ( $filesToBackup as $relativePath ) {
|
|
$sourcePath = $projectRoot . '/' . $relativePath;
|
|
if ( !file_exists( $sourcePath ) ) {
|
|
continue;
|
|
}
|
|
|
|
$targetPath = $backupDir . '/' . $relativePath;
|
|
$targetDir = dirname( $targetPath );
|
|
|
|
if ( !is_dir( $targetDir ) ) {
|
|
@mkdir( $targetDir, 0755, true );
|
|
}
|
|
|
|
if ( @copy( $sourcePath, $targetPath ) ) {
|
|
$backedUp++;
|
|
} else {
|
|
$log[] = '[WARNING] Nie udało się skopiować do backupu: ' . $relativePath;
|
|
}
|
|
}
|
|
|
|
$log[] = '[OK] Backup: skopiowano ' . $backedUp . ' plików';
|
|
|
|
@file_put_contents(
|
|
$backupDir . '/manifest.json',
|
|
json_encode( $manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE )
|
|
);
|
|
|
|
return $log;
|
|
}
|
|
|
|
/**
|
|
* Legacy — stary format aktualizacji (ZIP + _sql.txt + _files.txt).
|
|
*/
|
|
private function downloadAndApplyLegacy( string $ver, string $dir, array $log ): array
|
|
{
|
|
$baseUrl = 'https://shoppro.project-dc.pl/updates/' . $dir;
|
|
|
|
// Pobieranie ZIP
|
|
$zipUrl = $baseUrl . '/ver_' . $ver . '.zip';
|
|
$log[] = '[INFO] Pobieranie pliku ZIP: ' . $zipUrl;
|
|
$file = @file_get_contents( $zipUrl );
|
|
|
|
if ( $file === false ) {
|
|
$log[] = '[ERROR] Nie udało się pobrać pliku ZIP';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$fileSize = strlen( $file );
|
|
$log[] = '[OK] Pobrano plik ZIP, rozmiar: ' . $fileSize . ' bajtów';
|
|
|
|
if ( $fileSize < 100 ) {
|
|
$log[] = '[ERROR] Plik ZIP jest za mały (prawdopodobnie błąd pobierania)';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$dlHandler = @fopen( 'update.zip', 'w' );
|
|
if ( !$dlHandler ) {
|
|
$log[] = '[ERROR] Nie udało się otworzyć pliku update.zip do zapisu';
|
|
$log[] = '[INFO] Katalog roboczy: ' . getcwd();
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$written = fwrite( $dlHandler, $file );
|
|
fclose( $dlHandler );
|
|
|
|
if ( $written === false || $written === 0 ) {
|
|
$log[] = '[ERROR] Nie udało się zapisać pliku ZIP';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
|
|
$log[] = '[OK] Zapisano plik ZIP (' . $written . ' bajtów)';
|
|
|
|
// Wykonanie SQL
|
|
$log = $this->executeSql( $baseUrl . '/ver_' . $ver . '_sql.txt', $log );
|
|
|
|
// Usuwanie plików
|
|
$log = $this->deleteFiles( $baseUrl . '/ver_' . $ver . '_files.txt', $log );
|
|
|
|
// Rozpakowywanie ZIP
|
|
$log = $this->extractZip( 'update.zip', $log );
|
|
|
|
// Aktualizacja wersji
|
|
$versionFile = '../libraries/version.ini';
|
|
$handle = @fopen( $versionFile, 'w' );
|
|
if ( !$handle ) {
|
|
$log[] = '[ERROR] Nie udało się otworzyć pliku version.ini do zapisu';
|
|
return [ 'success' => false, 'log' => $log ];
|
|
}
|
|
fwrite( $handle, $ver );
|
|
fclose( $handle );
|
|
|
|
$log[] = '[OK] Zaktualizowano plik version.ini do wersji: ' . $ver;
|
|
$log[] = '[SUCCESS] Aktualizacja do wersji ' . $ver . ' zakończona pomyślnie';
|
|
|
|
return [ 'success' => true, 'log' => $log ];
|
|
}
|
|
|
|
private function executeSql( string $sqlUrl, array $log ): array
|
|
{
|
|
$log[] = '[INFO] Sprawdzanie aktualizacji SQL: ' . $sqlUrl;
|
|
|
|
$ch = curl_init( $sqlUrl );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
curl_setopt( $ch, CURLOPT_HEADER, false );
|
|
$response = curl_exec( $ch );
|
|
$contentType = curl_getinfo( $ch, CURLINFO_CONTENT_TYPE );
|
|
$httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
|
|
curl_close( $ch );
|
|
|
|
if ( !$response || strpos( $contentType, 'text/plain' ) === false ) {
|
|
$log[] = '[INFO] Brak aktualizacji SQL (HTTP: ' . $httpCode . ')';
|
|
return $log;
|
|
}
|
|
|
|
// Usunięcie UTF-8 BOM i normalizacja końców linii
|
|
$response = ltrim( $response, "\xEF\xBB\xBF" );
|
|
$response = str_replace( "\r\n", "\n", $response );
|
|
$response = str_replace( "\r", "\n", $response );
|
|
|
|
$queries = explode( "\n", $response );
|
|
$log[] = '[OK] Pobrano ' . count( $queries ) . ' zapytań SQL';
|
|
$success = 0;
|
|
$errors = 0;
|
|
|
|
foreach ( $queries as $query ) {
|
|
$query = trim( $query );
|
|
if ( $query !== '' ) {
|
|
if ( $this->db->query( $query ) ) {
|
|
$success++;
|
|
} else {
|
|
$errors++;
|
|
}
|
|
}
|
|
}
|
|
|
|
$log[] = '[INFO] Wykonano zapytania SQL - sukces: ' . $success . ', błędy: ' . $errors;
|
|
return $log;
|
|
}
|
|
|
|
private function deleteFiles( string $filesUrl, array $log ): array
|
|
{
|
|
$log[] = '[INFO] Sprawdzanie plików do usunięcia: ' . $filesUrl;
|
|
|
|
$ch = curl_init( $filesUrl );
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
|
|
curl_setopt( $ch, CURLOPT_HEADER, false );
|
|
$response = curl_exec( $ch );
|
|
$contentType = curl_getinfo( $ch, CURLINFO_CONTENT_TYPE );
|
|
curl_close( $ch );
|
|
|
|
if ( !$response || strpos( $contentType, 'text/plain' ) === false ) {
|
|
$log[] = '[INFO] Brak plików do usunięcia';
|
|
return $log;
|
|
}
|
|
|
|
$files = explode( PHP_EOL, $response );
|
|
$deletedFiles = 0;
|
|
$deletedDirs = 0;
|
|
|
|
foreach ( $files as $entry ) {
|
|
if ( strpos( $entry, 'F: ' ) !== false ) {
|
|
$path = substr( $entry, 3 );
|
|
if ( file_exists( $path ) ) {
|
|
if ( @unlink( $path ) ) {
|
|
$deletedFiles++;
|
|
} else {
|
|
$log[] = '[WARNING] Nie udało się usunąć pliku: ' . $path;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( strpos( $entry, 'D: ' ) !== false ) {
|
|
$path = substr( $entry, 3 );
|
|
if ( is_dir( $path ) ) {
|
|
\Shared\Helpers\Helpers::delete_dir( $path );
|
|
$deletedDirs++;
|
|
}
|
|
}
|
|
}
|
|
|
|
$log[] = '[INFO] Usunięto plików: ' . $deletedFiles . ', katalogów: ' . $deletedDirs;
|
|
return $log;
|
|
}
|
|
|
|
private function extractZip( string $fileName, array $log ): array
|
|
{
|
|
$log[] = '[INFO] Rozpoczęcie rozpakowywania pliku ZIP';
|
|
|
|
$path = pathinfo( realpath( $fileName ), PATHINFO_DIRNAME );
|
|
$path = substr( $path, 0, strlen( $path ) - 5 );
|
|
|
|
if ( !is_dir( $path ) || !is_writable( $path ) ) {
|
|
$log[] = '[ERROR] Ścieżka docelowa nie istnieje lub brak uprawnień: ' . $path;
|
|
return $log;
|
|
}
|
|
|
|
$zip = new \ZipArchive;
|
|
$res = $zip->open( $fileName );
|
|
|
|
if ( $res !== true ) {
|
|
$log[] = '[ERROR] Nie udało się otworzyć pliku ZIP (kod: ' . $res . ')';
|
|
return $log;
|
|
}
|
|
|
|
$log[] = '[OK] Otwarto archiwum ZIP, liczba plików: ' . $zip->numFiles;
|
|
$extracted = 0;
|
|
$errors = 0;
|
|
|
|
for ( $i = 0; $i < $zip->numFiles; $i++ ) {
|
|
$filename = str_replace( '\\', '/', $zip->getNameIndex( $i ) );
|
|
|
|
if ( substr( $filename, -1 ) === '/' ) {
|
|
$dirPath = $path . '/' . $filename;
|
|
if ( !is_dir( $dirPath ) ) {
|
|
@mkdir( $dirPath, 0755, true );
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$targetFile = $path . '/' . $filename;
|
|
$targetDir = dirname( $targetFile );
|
|
|
|
if ( !is_dir( $targetDir ) ) {
|
|
@mkdir( $targetDir, 0755, true );
|
|
}
|
|
|
|
$existed = file_exists( $targetFile );
|
|
$content = $zip->getFromIndex( $i );
|
|
|
|
if ( $content === false ) {
|
|
$log[] = '[ERROR] Nie udało się odczytać z ZIP: ' . $filename;
|
|
$errors++;
|
|
continue;
|
|
}
|
|
|
|
if ( @file_put_contents( $targetFile, $content ) === false ) {
|
|
$log[] = '[ERROR] Nie udało się zapisać: ' . $filename;
|
|
$errors++;
|
|
} else {
|
|
$tag = $existed ? '[UPDATED]' : '[NEW]';
|
|
$log[] = $tag . ' ' . $filename . ' (' . strlen( $content ) . ' bajtów)';
|
|
$extracted++;
|
|
}
|
|
}
|
|
|
|
$log[] = '[OK] Rozpakowano ' . $extracted . ' plików, błędów: ' . $errors;
|
|
$zip->close();
|
|
|
|
if ( @unlink( $fileName ) ) {
|
|
$log[] = '[OK] Usunięto plik update.zip';
|
|
}
|
|
|
|
return $log;
|
|
}
|
|
|
|
private function saveLog( array $log ): void
|
|
{
|
|
@file_put_contents( '../libraries/update_log.txt', implode( "\n", $log ) );
|
|
}
|
|
|
|
/**
|
|
* Wykonuje zaległe migracje z tabeli pp_updates.
|
|
*/
|
|
public function runPendingMigrations(): void
|
|
{
|
|
$results = $this->db->select( 'pp_updates', [ 'name' ], [ 'done' => 0 ] );
|
|
if ( !is_array( $results ) ) {
|
|
return;
|
|
}
|
|
|
|
foreach ( $results as $row ) {
|
|
$method = $row['name'];
|
|
if ( method_exists( $this, $method ) ) {
|
|
$this->$method();
|
|
}
|
|
}
|
|
}
|
|
|
|
public function update0197(): void
|
|
{
|
|
$rows = $this->db->select( 'pp_shop_order_products', [ 'id', 'product_id' ], [ 'parent_product_id' => null ] );
|
|
|
|
if ( is_array( $rows ) ) {
|
|
foreach ( $rows as $row ) {
|
|
$parentId = $this->db->get( 'pp_shop_products', 'parent_id', [ 'id' => $row['product_id'] ] );
|
|
$this->db->update( 'pp_shop_order_products', [
|
|
'parent_product_id' => $parentId ?: $row['product_id'],
|
|
], [ 'id' => $row['id'] ] );
|
|
}
|
|
}
|
|
|
|
$this->db->update( 'pp_updates', [ 'done' => 1 ], [ 'name' => 'update0197' ] );
|
|
}
|
|
}
|