Files
adsPRO/install.php
Jacek Pyziak 5e491d626c feat: Dodaj moduł grup i fraz, oznaczanie wykluczonych na czerwono, CLAUDE.md
- Nowy moduł CampaignTerms z widokiem grup reklam, fraz wyszukiwanych i fraz wykluczających
- Frazy wyszukiwane dodane do wykluczonych oznaczane czerwonym kolorem w tabeli
- Instalator migracji (install.php) z obsługą schema_migrations
- Migracja 003 dla tabel campaign_ad_groups, campaign_search_terms, campaign_negative_keywords
- CLAUDE.md z dokumentacją architektury projektu
- Aktualizacja layoutu, stylów i konfiguracji

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 23:44:30 +01:00

196 lines
4.3 KiB
PHP

<?php
error_reporting( E_ALL );
date_default_timezone_set( 'Europe/Warsaw' );
if ( PHP_SAPI !== 'cli' )
{
header( 'Content-Type: text/plain; charset=utf-8' );
}
require_once __DIR__ . '/config.php';
function has_flag( $name )
{
if ( PHP_SAPI === 'cli' )
{
global $argv;
return in_array( '--' . $name, $argv, true );
}
return isset( $_GET[ $name ] ) && (string) $_GET[ $name ] === '1';
}
function statement_complete( $buffer, $delimiter )
{
$trimmed = rtrim( $buffer );
if ( $trimmed === '' )
{
return false;
}
$dl = strlen( $delimiter );
if ( $dl === 0 )
{
return false;
}
return substr( $trimmed, -$dl ) === $delimiter;
}
function strip_statement_delimiter( $buffer, $delimiter )
{
$trimmed = rtrim( $buffer );
$dl = strlen( $delimiter );
if ( $dl > 0 && substr( $trimmed, -$dl ) === $delimiter )
{
return rtrim( substr( $trimmed, 0, -$dl ) );
}
return $trimmed;
}
function execute_sql_file( PDO $pdo, $file_path )
{
$handle = fopen( $file_path, 'r' );
if ( !$handle )
{
throw new RuntimeException( 'Nie mozna otworzyc pliku: ' . $file_path );
}
$delimiter = ';';
$buffer = '';
while ( ( $line = fgets( $handle ) ) !== false )
{
if ( preg_match( '/^\s*DELIMITER\s+(\S+)\s*$/i', $line, $m ) )
{
$delimiter = $m[1];
continue;
}
$trim = trim( $line );
if ( $trim !== '' && preg_match( '/^\s*(--|#)/', $trim ) )
{
continue;
}
$buffer .= $line;
if ( statement_complete( $buffer, $delimiter ) )
{
$statement = strip_statement_delimiter( $buffer, $delimiter );
$statement = trim( $statement );
if ( $statement !== '' )
{
$pdo -> exec( $statement );
}
$buffer = '';
}
}
fclose( $handle );
$tail = trim( $buffer );
if ( $tail !== '' )
{
$pdo -> exec( $tail );
}
}
try
{
$dsn = 'mysql:host=' . $database['host'] . ';dbname=' . $database['name'] . ';charset=utf8';
$pdo = new PDO( $dsn, $database['user'], $database['password'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
] );
$pdo -> exec(
'CREATE TABLE IF NOT EXISTS `schema_migrations` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`filename` VARCHAR(255) NOT NULL,
`applied_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_schema_migrations_filename` (`filename`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
);
$include_demo = has_flag( 'with_demo' );
$force = has_flag( 'force' );
$files = glob( __DIR__ . '/migrations/*.sql' );
sort( $files, SORT_NATURAL | SORT_FLAG_CASE );
$selected = [];
foreach ( $files as $file_path )
{
$filename = basename( $file_path );
if ( preg_match( '/^\d+_.+\.sql$/', $filename ) )
{
$selected[] = $file_path;
continue;
}
if ( $include_demo && $filename === 'demo_data.sql' )
{
$selected[] = $file_path;
}
}
if ( empty( $selected ) )
{
echo "Brak migracji do uruchomienia.\n";
exit;
}
echo "Uruchamianie migracji...\n";
echo 'Tryb force: ' . ( $force ? 'TAK' : 'NIE' ) . "\n";
echo 'Demo data: ' . ( $include_demo ? 'TAK' : 'NIE' ) . "\n\n";
$applied_count = 0;
$skipped_count = 0;
foreach ( $selected as $file_path )
{
$filename = basename( $file_path );
$stmt = $pdo -> prepare( 'SELECT COUNT(1) FROM schema_migrations WHERE filename = :filename' );
$stmt -> execute( [ ':filename' => $filename ] );
$already_applied = (int) $stmt -> fetchColumn() > 0;
if ( $already_applied && !$force )
{
echo '[SKIP] ' . $filename . " (juz zastosowana)\n";
$skipped_count++;
continue;
}
execute_sql_file( $pdo, $file_path );
$stmt = $pdo -> prepare(
'INSERT INTO schema_migrations (filename, applied_at)
VALUES (:filename, NOW())
ON DUPLICATE KEY UPDATE applied_at = NOW()'
);
$stmt -> execute( [ ':filename' => $filename ] );
echo '[OK] ' . $filename . "\n";
$applied_count++;
}
echo "\nZakonczono.\n";
echo 'Zastosowano: ' . $applied_count . "\n";
echo 'Pominieto: ' . $skipped_count . "\n";
}
catch ( Throwable $e )
{
http_response_code( 500 );
echo '[BLAD] ' . $e -> getMessage() . "\n";
exit( 1 );
}