| Current Path : /home/helpink/www/components/com_jbusinessdirectory/classes/services/ |
| Current File : /home/helpink/www/components/com_jbusinessdirectory/classes/services/AIService.php |
<?php
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Factory;
defined('JPATH_LIBRARIES') or die;
class AIService
{
private $apiKey;
private $apiEndpoint = 'https://api.openai.com/v1/chat/completions';
public function __construct($apiKey = null)
{
$this->apiKey = $apiKey ?: JBusinessUtil::getApplicationSettings()->ai_api_key;
}
/**
* Generates AI text content based on the given prompt and type
*
* @param string $prompt The user prompt to generate text from
* @param string $type The type of content (business, offer, event)
* @param string $field The field type (short, description)
* @param int $maxLength Maximum length of generated text
* @return string Generated text content
* @throws Exception If API key is missing or API call fails
*/
public function generateText($prompt, $type = 'business', $field = 'description', $maxLength = 500)
{
if (empty($this->apiKey)) {
throw new Exception('AI API key not configured');
}
// Adjust max tokens based on field type
$maxTokens = $field === 'short' ? 150 : $maxLength;
// Adjust temperature based on content type
$temperature = $this->getTemperatureForType($type, $field);
$systemPrompt = $this->getSystemPrompt($type, $field);
$data = [
'model' => 'gpt-3.5-turbo',
'messages' => [
[
'role' => 'system',
'content' => $systemPrompt
],
[
'role' => 'user',
'content' => $prompt
]
],
'max_tokens' => $maxTokens,
'temperature' => $temperature
];
$ch = curl_init($this->apiEndpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // Enable SSL verification
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // Verify the certificate's name against host
curl_setopt($ch, CURLOPT_CAINFO, JPATH_LIBRARIES . '/vendor/composer/ca-bundle/res/cacert.pem'); // Use Joomla's CA certificate bundle
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->apiKey
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($response === false) {
$error = curl_error($ch);
curl_close($ch);
throw new Exception('cURL Error: ' . $error);
}
curl_close($ch);
$result = json_decode($response, true);
if ($httpCode !== 200) {
$errorMessage = isset($result['error']['message']) ? $result['error']['message'] : 'Unknown API error';
throw new Exception('API Error (' . $httpCode . '): ' . $errorMessage);
}
if (!isset($result['choices'][0]['message']['content'])) {
throw new Exception('Invalid response format from API');
}
return $result['choices'][0]['message']['content'];
}
/**
* Gets the appropriate temperature setting based on content type and field
*
* @param string $type The type of content
* @param string $field The field type
* @return float Temperature value between 0 and 1
*/
private function getTemperatureForType($type, $field) {
// Use lower temperature for more focused/factual content
// Use higher temperature for more creative content
switch($type) {
case 'business':
return $field === 'short' ? 0.7 : 0.6;
case 'offer':
return $field === 'short' ? 0.8 : 0.7;
case 'event':
return $field === 'short' ? 0.8 : 0.7;
default:
return 0.7;
}
}
/**
* Gets the appropriate system prompt based on content type and field
*
* @param string $type The type of content (business, offer, event)
* @param string $field The field to generate text for (short, description)
* @return string The system prompt
*/
private static function getSystemPrompt($type = 'business', $field = 'description') {
$basePrompt = "You are a professional business content writer. ";
switch($type) {
case 'business':
if($field == 'short') {
return $basePrompt . "Write a concise and engaging summary that highlights the key aspects of the business. Focus on unique selling points, main services/products, and what makes this business stand out. Keep it professional but approachable.";
}
return $basePrompt . "Write a comprehensive business description that covers all important aspects including history, services/products, expertise, values, and unique selling propositions. The tone should be professional and informative while remaining engaging.";
case 'offer':
if($field == 'short') {
return $basePrompt . "Write a compelling and concise summary of this special offer or deal. Highlight the value proposition, key benefits, and any time-sensitive elements. The tone should create a sense of opportunity while maintaining professionalism.";
}
return $basePrompt . "Write a detailed description of the offer that includes all relevant information such as what's included, terms, benefits, and any special conditions. Focus on creating desire while clearly communicating all important details.";
case 'event':
if($field == 'short') {
return $basePrompt . "Write an engaging summary of this event that captures attention and communicates the essential details. Focus on what makes this event special and why people should attend. The tone should match the event's nature while remaining professional.";
}
return $basePrompt . "Write a comprehensive event description that covers all important aspects including program highlights, what attendees can expect, special features, and practical details. The tone should build excitement while providing clear information.";
default:
return $basePrompt . "Write clear, engaging, and professional content that effectively communicates the key information while maintaining reader interest.";
}
}
/**
* Loads all required language strings for AI text generation
* This should be called in the view file before any AI functionality is used
*
* @return void
*/
public static function loadLanguageStrings() {
$strings = [
'COM_JBUSINESSDIRECTORY_AI_GENERATE_TEXT',
'COM_JBUSINESSDIRECTORY_AI_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_GENERATE',
'COM_JBUSINESSDIRECTORY_AI_GENERATED_TEXT',
'COM_JBUSINESSDIRECTORY_AI_GENERATING',
'COM_JBUSINESSDIRECTORY_AI_ERROR',
'COM_JBUSINESSDIRECTORY_USE_TEXT',
'COM_JBUSINESSDIRECTORY_CANCEL',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_SLOGAN_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_DESCRIPTION_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_META_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_SHORT_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_OFFER_SHORT_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_OFFER_DESCRIPTION_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_EVENT_SHORT_PROMPT',
'COM_JBUSINESSDIRECTORY_AI_DEFAULT_EVENT_DESCRIPTION_PROMPT'
];
foreach ($strings as $string) {
Text::script($string);
}
}
/**
* Generates HTML for an AI suggestion button
*
* @param string $type The type of content (business, offer, event)
* @param string $field The type of field (short, description)
* @param string $targetField The ID of the target field to populate with generated text
* @param string $promptKey The language key for the prompt template
* @param array $promptReplacements Key-value pairs for placeholder replacements in the prompt
* @param string $language Optional language code for multilingual support
* @return string The HTML for the AI suggestion button
*/
public static function renderSuggestionButton($type, $field, $targetField, $promptKey, $promptReplacements = [], $language = '') {
$appSettings = JBusinessUtil::getApplicationSettings();
if (!$appSettings->enable_ai_suggestions) {
return '';
}
// Build the prompt with replacements
$prompt = Text::sprintf($promptKey, ...array_values($promptReplacements));
// Build onclick parameters
$params = [
"'$type'",
"'$field'",
"'$targetField'",
"'" . addslashes($prompt) . "'"
];
if ($language) {
$params[] = "'$language'";
}
$html = '<div class="ai-suggestion my-3">';
$html .= '<button type="button" class="btn btn-outline-primary" onclick="jbdAI.showTextGenerationPopup(' . implode(',', $params) . ')">';
$html .= '<i class="la la-magic"></i> ' . Text::_('LNG_AI_SUGGEST');
$html .= '</button>';
$html .= '</div>';
return $html;
}
}