prepareTaskText( $task_text ); if ( $api_key === '' ) return $this -> error( 'Brak klucza API OpenAI.' ); if ( $model === '' ) $model = 'gpt-5-nano'; if ( $task_text === '' ) return $this -> error( 'Brak tresci zadania do wygenerowania tytulu.' ); if ( !function_exists( 'curl_init' ) ) return $this -> error( 'Brak rozszerzenia cURL.' ); $payload = $this -> buildPayload( $model, $task_text ); $response = $this -> sendRequest( $api_key, $payload ); if ( $response['status'] !== 'success' ) return $response; $title = $this -> extractTitle( $response['body'] ); if ( $title === '' ) return $this -> error( 'OpenAI nie zwrocil poprawnego tytulu.' ); return [ 'status' => 'success', 'title' => $title ]; } private function buildPayload( $model, $task_text ) { $payload = [ 'model' => $model, 'messages' => [ [ 'role' => 'system', 'content' => 'Tworzysz bardzo krotkie, bezosobowe tytuly zadan w CRM. Odpowiadasz tylko tytulem, bez komentarza.' ], [ 'role' => 'user', 'content' => "Na podstawie tresci zadania zaproponuj jeden skrocony tytul po polsku.\n" . "Wymagania:\n" . "- maksymalnie 6 slow,\n" . "- forma bezosobowa rzeczownikowa, np. \"Usuniecie bloku o firmie\",\n" . "- bez trybu rozkazujacego i bez form typu \"usun\", \"dodaj\", \"popraw\",\n" . "- bez cudzyslowow,\n" . "- bez kropki na koncu,\n" . "- bez ogolnikow typu \"zadanie\" lub \"sprawa\".\n\n" . "Tresc zadania:\n" . $task_text ] ] ]; if ( stripos( $model, 'gpt-5' ) === 0 ) { $payload['reasoning_effort'] = 'minimal'; $payload['max_completion_tokens'] = 500; } else { $payload['temperature'] = 0.2; $payload['max_tokens'] = 80; } return $payload; } private function sendRequest( $api_key, array $payload ) { $ch = curl_init( self::ENDPOINT ); curl_setopt_array( $ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode( $payload ), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . $api_key ], CURLOPT_TIMEOUT => 20 ] ); $body = curl_exec( $ch ); $curl_error = curl_error( $ch ); $http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); curl_close( $ch ); if ( $body === false ) return $this -> error( 'Blad polaczenia z OpenAI: ' . $curl_error ); if ( (int)$http_code !== 200 ) return $this -> error( 'OpenAI zwrocil blad HTTP ' . (int)$http_code . ': ' . $this -> extractApiErrorMessage( $body ) ); if ( trim( (string)$body ) === '' ) return $this -> error( 'Pusta odpowiedz z OpenAI.' ); return [ 'status' => 'success', 'body' => (string)$body ]; } private function extractTitle( $response_body ) { $data = json_decode( (string)$response_body, true ); if ( !is_array( $data ) ) return ''; if ( isset( $data['error']['message'] ) ) return ''; $content = ''; if ( isset( $data['choices'][0]['message']['content'] ) ) $content = $this -> normalizeContent( $data['choices'][0]['message']['content'] ); $content = trim( preg_replace( '/\s+/', ' ', $content ) ); $content = trim( $content, " \t\n\r\0\x0B\"'`." ); if ( $content === '' ) return ''; return mb_substr( $content, 0, self::TITLE_LIMIT ); } private function normalizeContent( $content ) { if ( is_string( $content ) ) return $content; if ( !is_array( $content ) ) return ''; $parts = []; foreach ( $content as $item ) { if ( is_string( $item ) ) $parts[] = $item; elseif ( is_array( $item ) && isset( $item['text'] ) && is_string( $item['text'] ) ) $parts[] = $item['text']; elseif ( is_array( $item ) && isset( $item['text']['value'] ) && is_string( $item['text']['value'] ) ) $parts[] = $item['text']['value']; } return implode( ' ', $parts ); } private function prepareTaskText( $task_text ) { $task_text = html_entity_decode( (string)$task_text, ENT_QUOTES, 'UTF-8' ); $task_text = preg_replace( '/]*>.*?<\/script>/is', ' ', $task_text ); $task_text = preg_replace( '/]*>.*?<\/style>/is', ' ', $task_text ); $task_text = strip_tags( $task_text ); $task_text = preg_replace( '/\s+/', ' ', $task_text ); $task_text = trim( $task_text ); if ( $task_text === '' ) return ''; return mb_substr( $task_text, 0, self::CONTENT_LIMIT ); } private function extractApiErrorMessage( $response_body ) { $data = json_decode( (string)$response_body, true ); if ( is_array( $data ) && isset( $data['error']['message'] ) ) return (string)$data['error']['message']; return mb_substr( trim( (string)$response_body ), 0, 300 ); } private function error( $message ) { return [ 'status' => 'error', 'msg' => (string)$message ]; } }