- 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>
196 lines
4.3 KiB
PHP
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 );
|
|
}
|