autoDetect(); } } /** * Ortam bazlı otomatik ayarlama yapar * * PHP ayarlarına göre optimal chunk değerlerini hesaplar. * Shared hosting ortamlarında güvenli çalışmayı sağlar. * * @return self */ public function autoDetect(): self { // Max execution time ayarla $maxExecTime = (int) ini_get('max_execution_time'); if ($maxExecTime > 0) { // Timeout'tan 5 saniye önce durmalıyız $this->maxExecutionTime = max(10, $maxExecTime - 5); } // Memory limit'e göre ayarla $memoryLimit = $this->parseSize(ini_get('memory_limit')); if ($memoryLimit > 0) { // Toplam belleğin %20'sini buffer olarak tut $this->memoryBuffer = (int) ($memoryLimit * 0.2); // Düşük bellekli ortamlarda chunk boyutlarını küçült if ($memoryLimit < 128 * 1024 * 1024) { // 128MB'dan az $this->dbRowsPerChunk = 500; $this->filesPerChunk = 200; $this->maxZipSize = 25 * 1024 * 1024; // 25MB $this->sqlBatchSize = 50; } elseif ($memoryLimit < 256 * 1024 * 1024) { // 256MB'dan az $this->dbRowsPerChunk = 750; $this->filesPerChunk = 350; $this->maxZipSize = 40 * 1024 * 1024; // 40MB $this->sqlBatchSize = 75; } // 256MB ve üstü için varsayılan değerler kullanılır } // Upload max filesize'a göre ayarla $uploadMax = $this->parseSize(ini_get('upload_max_filesize')); $postMax = $this->parseSize(ini_get('post_max_size')); $effectiveUploadLimit = min($uploadMax, $postMax); if ($effectiveUploadLimit > 0) { // Upload chunk boyutunu limit'in yarısı yap (güvenlik payı) $this->uploadChunkSize = min( $this->uploadChunkSize, (int) ($effectiveUploadLimit / 2) ); // En az 512KB olsun $this->uploadChunkSize = max(524288, $this->uploadChunkSize); } return $this; } /** * PHP size string'ini byte'a çevirir (örn: "128M" -> 134217728) * * @param string $size PHP style size string * @return int Byte cinsinden değer */ private function parseSize(string $size): int { $size = trim($size); if (empty($size)) { return 0; } $unit = strtolower($size[strlen($size) - 1]); $value = (int) $size; switch ($unit) { case 'g': $value *= 1024 * 1024 * 1024; break; case 'm': $value *= 1024 * 1024; break; case 'k': $value *= 1024; break; } return $value; } // === GETTER METODLARI === public function getDbRowsPerChunk(): int { return $this->dbRowsPerChunk; } public function getFilesPerChunk(): int { return $this->filesPerChunk; } public function getMaxZipSize(): int { return $this->maxZipSize; } public function getUploadChunkSize(): int { return $this->uploadChunkSize; } public function getMaxExecutionTime(): int { return $this->maxExecutionTime; } public function getMemoryBuffer(): int { return $this->memoryBuffer; } public function getLargeFileThreshold(): int { return $this->largeFileThreshold; } public function getSqlBatchSize(): int { return $this->sqlBatchSize; } // === SETTER METODLARI === public function setDbRowsPerChunk(int $rows): self { $this->dbRowsPerChunk = max(100, $rows); // En az 100 return $this; } public function setFilesPerChunk(int $count): self { $this->filesPerChunk = max(10, $count); // En az 10 return $this; } public function setMaxZipSize(int $bytes): self { $this->maxZipSize = max(1024 * 1024, $bytes); // En az 1MB return $this; } public function setUploadChunkSize(int $bytes): self { $this->uploadChunkSize = max(524288, $bytes); // En az 512KB return $this; } public function setMaxExecutionTime(int $seconds): self { $this->maxExecutionTime = max(5, $seconds); // En az 5 saniye return $this; } public function setMemoryBuffer(int $bytes): self { $this->memoryBuffer = max(16 * 1024 * 1024, $bytes); // En az 16MB return $this; } public function setLargeFileThreshold(int $bytes): self { $this->largeFileThreshold = max(1024 * 1024, $bytes); // En az 1MB return $this; } public function setSqlBatchSize(int $count): self { $this->sqlBatchSize = max(10, min(500, $count)); // 10-500 arası return $this; } // === SERIALIZE METODLARI === /** * Konfigürasyonu array olarak döndürür (state kaydı için) * * @return array */ public function toArray(): array { return [ 'db_rows_per_chunk' => $this->dbRowsPerChunk, 'files_per_chunk' => $this->filesPerChunk, 'max_zip_size' => $this->maxZipSize, 'upload_chunk_size' => $this->uploadChunkSize, 'max_execution_time' => $this->maxExecutionTime, 'memory_buffer' => $this->memoryBuffer, 'large_file_threshold' => $this->largeFileThreshold, 'sql_batch_size' => $this->sqlBatchSize, ]; } /** * Array'den ChunkConfig oluşturur * * @param array $data * @return self */ public static function fromArray(array $data): self { $config = new self(false); // autoDetect kapalı if (isset($data['db_rows_per_chunk'])) { $config->setDbRowsPerChunk((int) $data['db_rows_per_chunk']); } if (isset($data['files_per_chunk'])) { $config->setFilesPerChunk((int) $data['files_per_chunk']); } if (isset($data['max_zip_size'])) { $config->setMaxZipSize((int) $data['max_zip_size']); } if (isset($data['upload_chunk_size'])) { $config->setUploadChunkSize((int) $data['upload_chunk_size']); } if (isset($data['max_execution_time'])) { $config->setMaxExecutionTime((int) $data['max_execution_time']); } if (isset($data['memory_buffer'])) { $config->setMemoryBuffer((int) $data['memory_buffer']); } if (isset($data['large_file_threshold'])) { $config->setLargeFileThreshold((int) $data['large_file_threshold']); } if (isset($data['sql_batch_size'])) { $config->setSqlBatchSize((int) $data['sql_batch_size']); } return $config; } /** * Kalan süreyi kontrol eder * * @param float $startTime microtime(true) ile alınmış başlangıç zamanı * @return bool True ise devam edilebilir, false ise durulmalı */ public function hasTimeRemaining(float $startTime): bool { $elapsed = microtime(true) - $startTime; return $elapsed < $this->maxExecutionTime; } /** * Bellek durumunu kontrol eder * * @return bool True ise yeterli bellek var, false ise durulmalı */ public function hasMemoryRemaining(): bool { $memoryLimit = $this->parseSize(ini_get('memory_limit')); // Unlimited memory if ($memoryLimit <= 0) { return true; } $usedMemory = memory_get_usage(true); $remaining = $memoryLimit - $usedMemory; return $remaining > $this->memoryBuffer; } /** * Hem süre hem bellek kontrolü yapar * * @param float $startTime microtime(true) ile alınmış başlangıç zamanı * @return bool True ise devam edilebilir */ public function canContinue(float $startTime): bool { return $this->hasTimeRemaining($startTime) && $this->hasMemoryRemaining(); } /** * Ortam bilgilerini özetler (debug için) * * @return array */ public function getEnvironmentSummary(): array { return [ 'php_memory_limit' => ini_get('memory_limit'), 'php_max_execution_time' => ini_get('max_execution_time'), 'php_upload_max_filesize' => ini_get('upload_max_filesize'), 'php_post_max_size' => ini_get('post_max_size'), 'configured' => $this->toArray(), ]; } }