Your project should not use deprecated PHP features 2
- Read doc
- Productivity
- Major
More information: https://insight.symfony.com/what-we-analyse/php.use_deprecated_function
- return true;
- }
- $finfo = finfo_open(FILEINFO_MIME_TYPE);
- $mimeType = finfo_file($finfo, $filePath);
- finfo_close($finfo);
- // Define allowed MIME types based on configured extensions
- $allowedMimeTypes = [
- // Images
- 'image/jpeg' => ['jpg', 'jpeg'],
- curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
- }
- $response = curl_exec($ch);
- $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
- if ($response === false) {
- return ['error' => ['message' => 'Stripe API request failed (curl).']];
- }
Your project should not use insecure random number functions
- Read doc
- Security
- Major
More information: https://insight.symfony.com/what-we-analyse/php.use_insecure_random_function
- // Fallback: use multiple sources of entropy
- // This should never happen on PHP 7.0+ but provides safety
- $fallback = hash('sha256',
- uniqid('antispam_', true) .
- microtime(true) .
- mt_rand() .
- (function_exists('random_bytes') ? bin2hex(random_bytes(16)) : '')
- );
- trigger_error(
- 'Failed to generate cryptographically secure secret, using fallback. Error: ' . $e->getMessage(),
Your project should use dedicated PHP string functions 55
- Read doc
- Productivity
- Info
More information: https://insight.symfony.com/what-we-analyse/php.use_string_function
- ['grow', 'shrink']
- ];
- // Check if goals contain contradictory terms
- foreach ($contradictions as $pair) {
- $has1in1 = strpos($goal1, $pair[0]) !== false;
- $has2in1 = strpos($goal1, $pair[1]) !== false;
- $has1in2 = strpos($goal2, $pair[0]) !== false;
- $has2in2 = strpos($goal2, $pair[1]) !== false;
- // If obj1 has first term and obj2 has second term (or vice versa)
- ];
- // Check if goals contain contradictory terms
- foreach ($contradictions as $pair) {
- $has1in1 = strpos($goal1, $pair[0]) !== false;
- $has2in1 = strpos($goal1, $pair[1]) !== false;
- $has1in2 = strpos($goal2, $pair[0]) !== false;
- $has2in2 = strpos($goal2, $pair[1]) !== false;
- // If obj1 has first term and obj2 has second term (or vice versa)
- if (($has1in1 && $has2in2) || ($has2in1 && $has1in2)) {
- // Check if goals contain contradictory terms
- foreach ($contradictions as $pair) {
- $has1in1 = strpos($goal1, $pair[0]) !== false;
- $has2in1 = strpos($goal1, $pair[1]) !== false;
- $has1in2 = strpos($goal2, $pair[0]) !== false;
- $has2in2 = strpos($goal2, $pair[1]) !== false;
- // If obj1 has first term and obj2 has second term (or vice versa)
- if (($has1in1 && $has2in2) || ($has2in1 && $has1in2)) {
- // Check if they're operating on similar subjects
- // Check if goals contain contradictory terms
- foreach ($contradictions as $pair) {
- $has1in1 = strpos($goal1, $pair[0]) !== false;
- $has2in1 = strpos($goal1, $pair[1]) !== false;
- $has1in2 = strpos($goal2, $pair[0]) !== false;
- $has2in2 = strpos($goal2, $pair[1]) !== false;
- // If obj1 has first term and obj2 has second term (or vice versa)
- if (($has1in1 && $has2in2) || ($has2in1 && $has1in2)) {
- // Check if they're operating on similar subjects
- $similarity = $this->calculateSimilarity($obj1, $obj2);
- 'database', 'table', 'index', 'query', 'cache', 'memory',
- 'file', 'log', 'configuration', 'setting', 'registry'
- ];
- foreach ($resourceKeywords as $keyword) {
- if (strpos($text, $keyword) !== false) {
- $resources[] = $keyword;
- }
- }
- return array_unique($resources);
- 'optimize' => ['optimize', 'improve', 'enhance', 'tune']
- ];
- foreach ($operationPatterns as $operation => $keywords) {
- foreach ($keywords as $keyword) {
- if (strpos($text, $keyword) !== false) {
- $operations[] = $operation;
- break;
- }
- }
- }
- if (isset($metadata['engines_used']) && is_array($metadata['engines_used'])) {
- $modesUsed = $metadata['engines_used'];
- $isHybrid = count($modesUsed) > 1;
- } elseif (isset($metadata['mode_type'])) {
- $modesUsed = [$metadata['mode_type']];
- $isHybrid = (strpos($metadata['mode_type'], 'hybrid') !== false);
- }
- // Display hybrid label if applicable
- if ($isHybrid) {
- $output .= "<strong>" . $this->language->getDef('text_rag_hybrid_search') . "</strong><br>";
- // Display mode badges
- $badges = [];
- foreach ($modesUsed as $mode) {
- $badge = '';
- if (strpos($mode, 'mode_a') !== false || strpos($mode, 'ai_overview') !== false) {
- $badge = "🤖 " . $this->language->getDef('text_rag_mode_ai_overview');
- } elseif (strpos($mode, 'mode_d') !== false || strpos($mode, 'amazon') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_amazon_shopping');
- } elseif (strpos($mode, 'mode_b') !== false || strpos($mode, 'shopping') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_shopping');
- foreach ($modesUsed as $mode) {
- $badge = '';
- if (strpos($mode, 'mode_a') !== false || strpos($mode, 'ai_overview') !== false) {
- $badge = "🤖 " . $this->language->getDef('text_rag_mode_ai_overview');
- } elseif (strpos($mode, 'mode_d') !== false || strpos($mode, 'amazon') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_amazon_shopping');
- } elseif (strpos($mode, 'mode_b') !== false || strpos($mode, 'shopping') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_shopping');
- } elseif (strpos($mode, 'mode_c') !== false || strpos($mode, 'rag') !== false) {
- $badge = "🔍 " . $this->language->getDef('text_rag_mode_rag_scraping');
- if (strpos($mode, 'mode_a') !== false || strpos($mode, 'ai_overview') !== false) {
- $badge = "🤖 " . $this->language->getDef('text_rag_mode_ai_overview');
- } elseif (strpos($mode, 'mode_d') !== false || strpos($mode, 'amazon') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_amazon_shopping');
- } elseif (strpos($mode, 'mode_b') !== false || strpos($mode, 'shopping') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_shopping');
- } elseif (strpos($mode, 'mode_c') !== false || strpos($mode, 'rag') !== false) {
- $badge = "🔍 " . $this->language->getDef('text_rag_mode_rag_scraping');
- } elseif (strpos($mode, 'mode_e') !== false || strpos($mode, 'google_trends') !== false) {
- $badge = "📈 " . $this->language->getDef('text_rag_mode_google_trends');
- $badge = "🤖 " . $this->language->getDef('text_rag_mode_ai_overview');
- } elseif (strpos($mode, 'mode_d') !== false || strpos($mode, 'amazon') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_amazon_shopping');
- } elseif (strpos($mode, 'mode_b') !== false || strpos($mode, 'shopping') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_shopping');
- } elseif (strpos($mode, 'mode_c') !== false || strpos($mode, 'rag') !== false) {
- $badge = "🔍 " . $this->language->getDef('text_rag_mode_rag_scraping');
- } elseif (strpos($mode, 'mode_e') !== false || strpos($mode, 'google_trends') !== false) {
- $badge = "📈 " . $this->language->getDef('text_rag_mode_google_trends');
- }
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_amazon_shopping');
- } elseif (strpos($mode, 'mode_b') !== false || strpos($mode, 'shopping') !== false) {
- $badge = "🛒 " . $this->language->getDef('text_rag_mode_shopping');
- } elseif (strpos($mode, 'mode_c') !== false || strpos($mode, 'rag') !== false) {
- $badge = "🔍 " . $this->language->getDef('text_rag_mode_rag_scraping');
- } elseif (strpos($mode, 'mode_e') !== false || strpos($mode, 'google_trends') !== false) {
- $badge = "📈 " . $this->language->getDef('text_rag_mode_google_trends');
- }
- if (!empty($badge)) {
- $badges[] = "<span class='badge badge-primary' style='margin-right: 10px; padding: 8px 12px; font-size: 0.9em;'>{$badge}</span>";
- ];
- // If extension has defined magic bytes, validate them
- if (isset($magicBytes[$extension])) {
- foreach ($magicBytes[$extension] as $magic) {
- if (strpos($bytes, $magic) === 0) {
- return true;
- }
- }
- return false;
- }
- // Simple contradiction check
- $s1Lower = strtolower($statement1);
- $s2Lower = strtolower($statement2);
- // Check for negation patterns
- if (strpos($s1Lower, 'not') !== false && strpos($s2Lower, 'not') === false) {
- return true;
- }
- return false;
- }
- * @return string Escaped value
- */
- private function escapeCsvValue(string $value): string
- {
- // Escape quotes and wrap in quotes if contains comma, quote, or newline
- if (strpos($value, ',') !== false || strpos($value, '"') !== false || strpos($value, "\n") !== false) {
- return '"' . str_replace('"', '""', $value) . '"';
- }
- return $value;
- }
- // Propose permission level always requires approval for write actions
- if ($permissionLevel === self::PERMISSION_PROPOSE) {
- $writeActions = ['create', 'update', 'delete', 'modify', 'propose'];
- foreach ($writeActions as $writeAction) {
- if (strpos($action, $writeAction) !== false) {
- return true;
- }
- }
- }
- $text = strtolower("$reason $comment");
- foreach ($keywords as $type => $words) {
- foreach ($words as $word) {
- if (strpos($text, $word) !== false) {
- return $type;
- }
- }
- }
- // 🔍 DEBUG: Log prompt loading verification
- if ($this->debug) {
- error_log("[INFO : ANALYSE] [UnifiedQueryAnalyzer] Prompt Loading Verification:");
- error_log(" Prompt length: " . strlen($prompt) . " characters");
- error_log(" Prompt preview (first 200 chars): " . substr($prompt, 0, 200) . "...");
- error_log(" Query in prompt: " . (strpos($prompt, $query) !== false ? 'YES' : 'NO'));
- }
- // Single GPT call for everything
- // Use Gpt::getGptResponse() instead of non-existent complete() method
- if ($this->debug) {
- error_log("UnifiedQueryAnalyzer: Built prompt from language file sections");
- error_log("UnifiedQueryAnalyzer: Query to analyze: {$query}");
- error_log("UnifiedQueryAnalyzer: Total prompt length: " . strlen($prompt) . " characters");
- error_log("UnifiedQueryAnalyzer: Prompt contains query: " . (strpos($prompt, $query) !== false ? 'YES' : 'NO'));
- }
- return $prompt;
- }
- */
- private function categorizeError(string $errorMessage): string
- {
- $message = strtolower($errorMessage);
- if (strpos($message, 'database') !== false || strpos($message, 'sql') !== false) {
- return 'database';
- }
- if (strpos($message, 'timeout') !== false || strpos($message, 'time out') !== false) {
- return 'timeout';
- }
- $message = strtolower($errorMessage);
- if (strpos($message, 'database') !== false || strpos($message, 'sql') !== false) {
- return 'database';
- }
- if (strpos($message, 'timeout') !== false || strpos($message, 'time out') !== false) {
- return 'timeout';
- }
- if (strpos($message, 'memory') !== false) {
- return 'memory';
- }
- return 'database';
- }
- if (strpos($message, 'timeout') !== false || strpos($message, 'time out') !== false) {
- return 'timeout';
- }
- if (strpos($message, 'memory') !== false) {
- return 'memory';
- }
- if (strpos($message, 'validation') !== false || strpos($message, 'invalid') !== false) {
- return 'validation';
- }
- return 'timeout';
- }
- if (strpos($message, 'memory') !== false) {
- return 'memory';
- }
- if (strpos($message, 'validation') !== false || strpos($message, 'invalid') !== false) {
- return 'validation';
- }
- if (strpos($message, 'classification') !== false || strpos($message, 'intent') !== false) {
- return 'classification';
- }
- return 'memory';
- }
- if (strpos($message, 'validation') !== false || strpos($message, 'invalid') !== false) {
- return 'validation';
- }
- if (strpos($message, 'classification') !== false || strpos($message, 'intent') !== false) {
- return 'classification';
- }
- if (strpos($message, 'api') !== false || strpos($message, 'gpt') !== false) {
- return 'api';
- }
- return 'validation';
- }
- if (strpos($message, 'classification') !== false || strpos($message, 'intent') !== false) {
- return 'classification';
- }
- if (strpos($message, 'api') !== false || strpos($message, 'gpt') !== false) {
- return 'api';
- }
- return 'unknown';
- }
- // If it's an array, search for the response
- if (is_array($executionResult)) {
- if (isset($executionResult['text_response']) && !empty($executionResult['text_response'])) {
- // Check if text_response is NOT the JSON fallback
- if (strpos($executionResult['text_response'], 'Résultat:') === false) {
- return $executionResult['text_response'];
- }
- }
- if (isset($executionResult['response']) && !empty($executionResult['response'])) {
- }
- }
- // Priority 4: Check if rawResult has 'text_response' field (but not if it's the JSON fallback)
- if (isset($rawResult['text_response']) && !empty($rawResult['text_response'])) {
- if (strpos($rawResult['text_response'], 'Résultat:') === false) {
- return $rawResult['text_response'];
- }
- }
- // Priority 5: Use finalResponse if available (but not if it's the JSON fallback)
- return $rawResult['text_response'];
- }
- }
- // Priority 5: Use finalResponse if available (but not if it's the JSON fallback)
- if (!empty($finalResponse) && strpos($finalResponse, 'Résultat:') === false) {
- return $finalResponse;
- }
- return '';
- }
- // Check if source type is valid (case-insensitive, partial match)
- $sourceType = strtolower($sourceAttr['source_type']);
- $isValidSource = false;
- foreach ($validSourceTypes as $validType) {
- if (strpos($sourceType, strtolower($validType)) !== false) {
- $isValidSource = true;
- break;
- }
- }
- 'as an ai',
- 'i\'m an ai'
- ];
- foreach ($genericPhrases as $phrase) {
- if (strpos($response, $phrase) !== false) {
- $validationErrors[] = "Response contains generic LLM phrase indicating lack of knowledge";
- return false;
- }
- }
- $table = $matches[1];
- }
- // Ajouter le préfixe si nécessaire
- $prefix = CLICSHOPPING::getConfig('db_prefix');
- if (!empty($prefix) && strpos($table, $prefix) !== 0) {
- $table = $prefix . $table;
- }
- return trim($table, '`"\'');
- }
- private function determineSuggestedActionForSqlError(string $errorMessage, string $temporalPeriod): string
- {
- $errorLower = strtolower($errorMessage);
- // Check for common error patterns
- if (strpos($errorLower, 'column') !== false || strpos($errorLower, 'field') !== false) {
- return "The database may not have the required columns for {$temporalPeriod} aggregation. Try a different time period or check your data schema.";
- }
- if (strpos($errorLower, 'table') !== false) {
- return "The required table for {$temporalPeriod} aggregation may not exist. Verify your database structure.";
- // Check for common error patterns
- if (strpos($errorLower, 'column') !== false || strpos($errorLower, 'field') !== false) {
- return "The database may not have the required columns for {$temporalPeriod} aggregation. Try a different time period or check your data schema.";
- }
- if (strpos($errorLower, 'table') !== false) {
- return "The required table for {$temporalPeriod} aggregation may not exist. Verify your database structure.";
- }
- if (strpos($errorLower, 'syntax') !== false) {
- return "There was a SQL syntax error. Try rephrasing your query or using a simpler time period.";
- if (strpos($errorLower, 'table') !== false) {
- return "The required table for {$temporalPeriod} aggregation may not exist. Verify your database structure.";
- }
- if (strpos($errorLower, 'syntax') !== false) {
- return "There was a SQL syntax error. Try rephrasing your query or using a simpler time period.";
- }
- if (strpos($errorLower, 'permission') !== false || strpos($errorLower, 'access') !== false) {
- return "You may not have permission to access the required data. Contact your administrator.";
- if (strpos($errorLower, 'syntax') !== false) {
- return "There was a SQL syntax error. Try rephrasing your query or using a simpler time period.";
- }
- if (strpos($errorLower, 'permission') !== false || strpos($errorLower, 'access') !== false) {
- return "You may not have permission to access the required data. Contact your administrator.";
- }
- if (strpos($errorLower, 'timeout') !== false) {
- return "The query took too long. Try a shorter time range or simpler aggregation.";
- if (strpos($errorLower, 'permission') !== false || strpos($errorLower, 'access') !== false) {
- return "You may not have permission to access the required data. Contact your administrator.";
- }
- if (strpos($errorLower, 'timeout') !== false) {
- return "The query took too long. Try a shorter time range or simpler aggregation.";
- }
- // Default suggestion
- return "Try rephrasing your query or using a different temporal period. If the problem persists, contact support.";
- // Semantic results MUST have sources OR data, unless it's a valid LLM/memory fallback
- if (!$hasSources) {
- $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
- $isLLMFallback = $hasTextResponse && (
- strpos($sourceType, 'llm') !== false ||
- strpos($sourceType, 'general knowledge') !== false ||
- strpos($sourceType, 'conversation') !== false ||
- strpos($sourceType, 'memory') !== false
- );
- // Semantic results MUST have sources OR data, unless it's a valid LLM/memory fallback
- if (!$hasSources) {
- $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
- $isLLMFallback = $hasTextResponse && (
- strpos($sourceType, 'llm') !== false ||
- strpos($sourceType, 'general knowledge') !== false ||
- strpos($sourceType, 'conversation') !== false ||
- strpos($sourceType, 'memory') !== false
- );
- if (!$isLLMFallback) {
- if (!$hasSources) {
- $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
- $isLLMFallback = $hasTextResponse && (
- strpos($sourceType, 'llm') !== false ||
- strpos($sourceType, 'general knowledge') !== false ||
- strpos($sourceType, 'conversation') !== false ||
- strpos($sourceType, 'memory') !== false
- );
- if (!$isLLMFallback) {
- $sourcesStatus = isset($finalResult['sources']) ? 'empty' : 'not set';
- $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
- $isLLMFallback = $hasTextResponse && (
- strpos($sourceType, 'llm') !== false ||
- strpos($sourceType, 'general knowledge') !== false ||
- strpos($sourceType, 'conversation') !== false ||
- strpos($sourceType, 'memory') !== false
- );
- if (!$isLLMFallback) {
- $sourcesStatus = isset($finalResult['sources']) ? 'empty' : 'not set';
- $dataStatus = isset($finalResult['data']) ? 'empty' : 'not set';
- private function generateUserFriendlyErrorMessage(array $errors): string
- {
- // Check for common error patterns and generate appropriate messages
- foreach ($errors as $error) {
- // Pattern: "Semantic result missing sources and data"
- if (strpos($error, 'Semantic result missing sources and data') !== false) {
- return "I couldn't find any information about that in the database. The requested content (like terms and conditions) may not be available yet. Please try asking about something else or contact support to add this content.";
- }
- // Pattern: "Analytics result missing data"
- if (strpos($error, 'Analytics result missing data') !== false) {
- if (strpos($error, 'Semantic result missing sources and data') !== false) {
- return "I couldn't find any information about that in the database. The requested content (like terms and conditions) may not be available yet. Please try asking about something else or contact support to add this content.";
- }
- // Pattern: "Analytics result missing data"
- if (strpos($error, 'Analytics result missing data') !== false) {
- return "I couldn't retrieve the requested data. This might be because there are no records matching your query, or the data hasn't been entered yet. Please try a different query or check if the data exists.";
- }
- // Pattern: "Hybrid result missing"
- if (strpos($error, 'Hybrid result missing') !== false) {
- if (strpos($error, 'Analytics result missing data') !== false) {
- return "I couldn't retrieve the requested data. This might be because there are no records matching your query, or the data hasn't been entered yet. Please try a different query or check if the data exists.";
- }
- // Pattern: "Hybrid result missing"
- if (strpos($error, 'Hybrid result missing') !== false) {
- return "I couldn't complete your request because some of the required information is missing. Please try breaking your question into smaller parts or asking about something else.";
- }
- // Pattern: "Empty response"
- if (strpos($error, 'empty') !== false || strpos($error, 'Empty') !== false) {
- if (strpos($error, 'Hybrid result missing') !== false) {
- return "I couldn't complete your request because some of the required information is missing. Please try breaking your question into smaller parts or asking about something else.";
- }
- // Pattern: "Empty response"
- if (strpos($error, 'empty') !== false || strpos($error, 'Empty') !== false) {
- return "I couldn't find any results for your query. The information you're looking for might not be available in the system yet. Please try rephrasing your question or asking about something else.";
- }
- }
- // Default fallback message
- // Fallback to source_table if no name found
- if ($docName === null && isset($metadata['source_table'])) {
- $tableName = $metadata['source_table'];
- // Remove prefix and _embedding suffix
- $prefix = defined('CLICSHOPPING_DB_TABLE_PREFIX') ? CLICSHOPPING_DB_TABLE_PREFIX : 'clic_';
- if (strpos($tableName, $prefix) === 0) {
- $tableName = substr($tableName, strlen($prefix));
- }
- $tableName = str_replace('_embedding', '', $tableName);
- $tableName = str_replace('_', ' ', $tableName);
- $docName = ucwords($tableName);
- return $entityType;
- }
- // Remove table prefix if present
- $prefix = CLICSHOPPING::getConfig('db_table_prefix');
- if (!empty($prefix) && strpos($tableName, $prefix) === 0) {
- $tableName = substr($tableName, strlen($prefix));
- }
- // Remove '_embedding' suffix if present
- $tableName = str_replace('_embedding', '', $tableName);
- }
- $keywords[] = $entityType;
- $keywords[] = str_replace('_', ' ', $entityType);
- if (substr($entityType, -3) === 'ies') {
- $keywords[] = substr($entityType, 0, -3) . 'y';
- } elseif (substr($entityType, -1) === 's') {
- $keywords[] = substr($entityType, 0, -1);
- } else {
- $keywords[] = $entityType . 's';
- $keywords[] = $entityType;
- $keywords[] = str_replace('_', ' ', $entityType);
- if (substr($entityType, -3) === 'ies') {
- $keywords[] = substr($entityType, 0, -3) . 'y';
- } elseif (substr($entityType, -1) === 's') {
- $keywords[] = substr($entityType, 0, -1);
- } else {
- $keywords[] = $entityType . 's';
- }
- }
- * @return bool
- */
- private function hasKeyword(string $text, array $keywords): bool
- {
- foreach ($keywords as $keyword) {
- if (strpos($text, $keyword) !== false) {
- return true;
- }
- }
- return false;
- }
- // Simple keyword matching (replaces deleted PatternAnalysisPattern)
- $patternKeywords = ['pattern', 'trend', 'style', 'dominant', 'recurring', 'common'];
- $queryLower = strtolower($queryToAnalyze);
- foreach ($patternKeywords as $keyword) {
- if (strpos($queryLower, $keyword) !== false) {
- if ($this->debug) {
- $this->logDebug("Pattern analysis keyword detected: $keyword");
- }
- return true;
- }
- // Format: ['table' => 'column']
- $table = $key;
- $column = $value;
- } else {
- // Format: ['table.column']
- if (strpos($value, '.') !== false) {
- list($table, $column) = explode('.', $value, 2);
- } else {
- // Cannot validate without table context
- if ($this->debug) {
- error_log("SchemaValidator: Column '{$value}' has no table context");
- * @param string $sql The SQL query
- * @return bool True if comments found
- */
- private function hasComments(string $sql): bool
- {
- return preg_match('/--/', $sql) || preg_match('/\/\*/', $sql);
- }
- /**
- * Check if query contains UNION statement.
- *
- public static function extractBaseMetric(string $query): ?string
- {
- $query = strtolower($query);
- foreach (self::FINANCIAL_METRICS as $pattern => $metric) {
- if (strpos($query, $pattern) !== false) {
- return $metric;
- }
- }
- return null;
- return "year {$matches[2]}";
- }
- // Check for relative time patterns
- foreach (self::RELATIVE_TIME_PATTERNS as $pattern => $range) {
- if (strpos($query, $pattern) !== false) {
- return $range;
- }
- }
- return null;
- $lowerQuery = strtolower($query);
- $needsContext = false;
- foreach ($contextualKeywords as $keyword) {
- if (strpos($lowerQuery, $keyword) !== false) {
- $needsContext = true;
- break;
- }
- }
Your project uses legacy callable syntax instead of first-class callable syntax 3
- Read doc
- Productivity
- Info
More information: https://insight.symfony.com/what-we-analyse/php.use_first_class_callable_syntax
- foreach ($schema['foreign'] as $name => $fields) {
- // Escape foreign key name for SQL injection protection
- $escaped_fk_name = self::prepareIdentifier($name);
- // Escape column names in foreign key definition
- $escaped_cols = array_map([self::class, 'prepareIdentifier'], $fields['col']);
- $escaped_ref_cols = array_map([self::class, 'prepareIdentifier'], $fields['ref_col']);
- // Escape reference table name
- $escaped_ref_table = self::prepareIdentifier($fields['ref_table']);
- // Escape foreign key name for SQL injection protection
- $escaped_fk_name = self::prepareIdentifier($name);
- // Escape column names in foreign key definition
- $escaped_cols = array_map([self::class, 'prepareIdentifier'], $fields['col']);
- $escaped_ref_cols = array_map([self::class, 'prepareIdentifier'], $fields['ref_col']);
- // Escape reference table name
- $escaped_ref_table = self::prepareIdentifier($fields['ref_table']);
- $row = ' FOREIGN KEY ' . $escaped_fk_name . ' (' . implode(', ', $escaped_cols) . ') REFERENCES ' . (isset($prefix) && (!isset($fields['prefix']) || ($fields['prefix'] != 'false')) ? $prefix : '') . $escaped_ref_table . '(' . implode(', ', $escaped_ref_cols) . ')';
- // Build a mapping of table names (without prefix) to entity types
- $tableToEntityType = [];
- foreach ($allTables as $fullTableName) {
- $entityType = $registry->getEntityTypeForTable($fullTableName);
- // Remove prefix and _embedding suffix to get base table name
- $tableName = str_replace([$prefix, '_embedding'], '', $fullTableName);
- $tableToEntityType[$tableName] = $entityType;
- }
- // Pattern 1: FROM {table_name}
- if (preg_match('/FROM\s+(?:\w+\.)?(\w+)/i', $query, $matches)) {