Your project uses non-strict array lookups 5

More information: https://insight.symfony.com/what-we-analyse/php.strict_array_lookup

  1. // Use higher priority
  2. $priorities = ['low' => 1, 'medium' => 2, 'high' => 3, 'critical' => 4];
  3. $priority1 = $priorities[$obj1->getPriority()];
  4. $priority2 = $priorities[$obj2->getPriority()];
  5. $combinedPriority = array_search(max($priority1, $priority2), $priorities);
    array_search() should be called with the third parameter set to true to enable strict comparison and avoid type juggling bugs.
    Time to fix: about 15 minutes
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. // Estimate combined time (not just sum, as there may be synergies)
  7. $estimatedTime = (int)(($obj1->getEstimatedCompletionTime() + $obj2->getEstimatedCompletionTime()) * 0.8);
  8. return [
  • gyakutsuki

    not implemented
  • gyakutsuki

    not included
  1. unset($this->storage[$scopedKey]);
  2. unset($this->metadata[$scopedKey]);
  3. // Remove from the scope's key list
  4. $scopeKeys = $this->scopes[$this->currentScope] ?? [];
  5. $index = array_search($scopedKey, $scopeKeys);
    array_search() should be called with the third parameter set to true to enable strict comparison and avoid type juggling bugs.
    Time to fix: about 15 minutes
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. if ($index !== false) {
  7. array_splice($this->scopes[$this->currentScope], $index, 1);
  8. }
  • gyakutsuki

    not implemented
  • gyakutsuki

    not included
  1. <?php
  2. foreach ($modules as $module) {
  3. $secCheck = $GLOBALS[$module['class']];
  4. if (!\in_array($secCheck->type, $types)) {
    in_array() should be called with the third parameter set to true to enable strict comparison and avoid type juggling bugs.
    Time to fix: about 15 minutes
    Read doc Permalink Copy Prompt
    Last edited by ClicShopping
  5. $secCheck->type = 'info';
  6. }
  7. $output = '';
  • gyakutsuki

    not implemented
  • gyakutsuki

    not included
  1. }
  2. }
  3. if (!empty($this->_upload)) {
  4. if (!empty($this->_extensions)) {
  5. if (!in_array(mb_strtolower(substr($this->_upload['name'], strrpos($this->_upload['name'], '.') + 1)), $this->_extensions)) {
    in_array() should be called with the third parameter set to true to enable strict comparison and avoid type juggling bugs.
    Time to fix: about 15 minutes
    Read doc Permalink Copy Prompt
    Last edited by ClicShopping
  6. $CLICSHOPPING_MessageStack->add(CLICSHOPPING::getDef('error_filetype_not_allowed') . implode(', ', $this->_extensions), 'warning');
  7. return false;
  8. }
  9. }
  • gyakutsuki

    not implemented
  • gyakutsuki

    not included
  1. while ($file = $dir->read()) {
  2. if (!is_dir($backup_directory . $file)) {
  3. $ext = substr($file, strrpos($file, '.') + 1);
  4. if (in_array($ext, array('zip', 'sql', 'gz')) && !isset($contents[$ext])) {
    in_array() should be called with the third parameter set to true to enable strict comparison and avoid type juggling bugs.
    Time to fix: about 15 minutes
    Read doc Permalink Copy Prompt
    Last edited by ClicShopping
  5. $contents[$ext] = $file;
  6. if ($ext != 'sql') { // zip and gz (binaries) are prioritized over sql (plain text)
  7. break;
  8. }
  • gyakutsuki

    not implemented
  • gyakutsuki

    not included

Your project should not use insecure random number functions 2

More information: https://insight.symfony.com/what-we-analyse/php.use_insecure_random_function

  1. // Boucle infinie pour l'envoi des événements
  2. while (true) {
  3. try {
  4. // Simulate random failure before computing data
  5. if ($sim_fail_rate > 0 && mt_rand(0, mt_getrandmax()) / mt_getrandmax() < $sim_fail_rate) {
    The function mt_rand() is not cryptographically secure. Use random_int() or random_bytes() instead.
    Time to fix: about 2 hours
    Read doc Permalink Copy Prompt
    Last edited by ClicShopping
  6. throw new \Exception('Simulated failure');
  7. }
  8. // Récupérer les données de performance
  9. $data = $monitor->getPerformanceData($range);
  • gyakutsuki

    Ignored on Wed, 22 Apr 2026 13:21:26 GMT
  1. $data['metrics']['error_frequency'] = max(0.0, (float)$sim_error_pct);
  2. }
  3. }
  4. // Optionally force a random connection drop to test auto-reconnect
  5. if ($sim_drop && (mt_rand(1, 100) <= 5)) { // ~5% chance per tick
    The function mt_rand() is not cryptographically secure. Use random_int() or random_bytes() instead.
    Time to fix: about 2 hours
    Read doc Permalink Copy Prompt
    Last edited by ClicShopping
  6. // Flush a final event then terminate the connection
  7. echo "event: error\n";
  8. echo "data: {\"error\":\"Simulated connection drop\"}\n\n";
  9. ob_flush();
  10. flush();
  • gyakutsuki

    Ignored on Wed, 22 Apr 2026 13:21:05 GMT

Your project should not contain PHP files defining multiple classes

More information: https://insight.symfony.com/what-we-analyse/php.file_contains_more_than_one_class

This file contains 2 classes. Keeping only one class per file is a standard in the PHP community, since it promotes interoperability and maintainability.
Time to fix: about 4 hours
Read doc Permalink Copy Prompt
Last edited by ClicShopping
  • he_header_multi_template (defined at line 16)
  • explodeCategoryTree (defined at line 238)
  • gyakutsuki

    Ignored on Thu, 18 Sep 2025 15:32:21 GMT

Your project should use dedicated PHP string functions 50

More information: https://insight.symfony.com/what-we-analyse/php.use_string_function

  1. private function determineSuggestedActionForSqlError(string $errorMessage, string $temporalPeriod): string
  2. {
  3. $errorLower = strtolower($errorMessage);
  4. // Check for common error patterns
  5. if (strpos($errorLower, 'column') !== false || strpos($errorLower, 'field') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return "The database may not have the required columns for {$temporalPeriod} aggregation. Try a different time period or check your data schema.";
  7. }
  8. if (strpos($errorLower, 'table') !== false) {
  9. return "The required table for {$temporalPeriod} aggregation may not exist. Verify your database structure.";
  • gyakutsuki

    not included
  1. if (strpos($errorLower, 'syntax') !== false) {
  2. return "There was a SQL syntax error. Try rephrasing your query or using a simpler time period.";
  3. }
  4. if (strpos($errorLower, 'permission') !== false || strpos($errorLower, 'access') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  5. return "You may not have permission to access the required data. Contact your administrator.";
  6. }
  7. if (strpos($errorLower, 'timeout') !== false) {
  8. return "The query took too long. Try a shorter time range or simpler aggregation.";
  • gyakutsuki

    not included
  1. if (strpos($errorLower, 'permission') !== false || strpos($errorLower, 'access') !== false) {
  2. return "You may not have permission to access the required data. Contact your administrator.";
  3. }
  4. if (strpos($errorLower, 'timeout') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  5. return "The query took too long. Try a shorter time range or simpler aggregation.";
  6. }
  7. // Default suggestion
  8. return "Try rephrasing your query or using a different temporal period. If the problem persists, contact support.";
  • gyakutsuki

    not included
  1. if (strpos($errorLower, 'table') !== false) {
  2. return "The required table for {$temporalPeriod} aggregation may not exist. Verify your database structure.";
  3. }
  4. if (strpos($errorLower, 'syntax') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  5. return "There was a SQL syntax error. Try rephrasing your query or using a simpler time period.";
  6. }
  7. if (strpos($errorLower, 'permission') !== false || strpos($errorLower, 'access') !== false) {
  8. return "You may not have permission to access the required data. Contact your administrator.";
  • gyakutsuki

    not included
  1. // Check for common error patterns
  2. if (strpos($errorLower, 'column') !== false || strpos($errorLower, 'field') !== false) {
  3. return "The database may not have the required columns for {$temporalPeriod} aggregation. Try a different time period or check your data schema.";
  4. }
  5. if (strpos($errorLower, 'table') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return "The required table for {$temporalPeriod} aggregation may not exist. Verify your database structure.";
  7. }
  8. if (strpos($errorLower, 'syntax') !== false) {
  9. return "There was a SQL syntax error. Try rephrasing your query or using a simpler time period.";
  • gyakutsuki

    not included
  1. // Propose permission level always requires approval for write actions
  2. if ($permissionLevel === self::PERMISSION_PROPOSE) {
  3. $writeActions = ['create', 'update', 'delete', 'modify', 'propose'];
  4. foreach ($writeActions as $writeAction) {
  5. if (strpos($action, $writeAction) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return true;
  7. }
  8. }
  9. }
  • gyakutsuki

    not included
  1. 'database', 'table', 'index', 'query', 'cache', 'memory',
  2. 'file', 'log', 'configuration', 'setting', 'registry'
  3. ];
  4. foreach ($resourceKeywords as $keyword) {
  5. if (strpos($text, $keyword) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $resources[] = $keyword;
  7. }
  8. }
  9. return array_unique($resources);
  • gyakutsuki

    not included
  1. 'optimize' => ['optimize', 'improve', 'enhance', 'tune']
  2. ];
  3. foreach ($operationPatterns as $operation => $keywords) {
  4. foreach ($keywords as $keyword) {
  5. if (strpos($text, $keyword) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $operations[] = $operation;
  7. break;
  8. }
  9. }
  10. }
  • gyakutsuki

    not included
  1. // Check if goals contain contradictory terms
  2. foreach ($contradictions as $pair) {
  3. $has1in1 = strpos($goal1, $pair[0]) !== false;
  4. $has2in1 = strpos($goal1, $pair[1]) !== false;
  5. $has1in2 = strpos($goal2, $pair[0]) !== false;
  6. $has2in2 = strpos($goal2, $pair[1]) !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. // If obj1 has first term and obj2 has second term (or vice versa)
  8. if (($has1in1 && $has2in2) || ($has2in1 && $has1in2)) {
  9. // Check if they're operating on similar subjects
  10. $similarity = $this->calculateSimilarity($obj1, $obj2);
  • gyakutsuki

    not included
  1. ];
  2. // Check if goals contain contradictory terms
  3. foreach ($contradictions as $pair) {
  4. $has1in1 = strpos($goal1, $pair[0]) !== false;
  5. $has2in1 = strpos($goal1, $pair[1]) !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $has1in2 = strpos($goal2, $pair[0]) !== false;
  7. $has2in2 = strpos($goal2, $pair[1]) !== false;
  8. // If obj1 has first term and obj2 has second term (or vice versa)
  9. if (($has1in1 && $has2in2) || ($has2in1 && $has1in2)) {
  • gyakutsuki

    not included
  1. ['grow', 'shrink']
  2. ];
  3. // Check if goals contain contradictory terms
  4. foreach ($contradictions as $pair) {
  5. $has1in1 = strpos($goal1, $pair[0]) !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $has2in1 = strpos($goal1, $pair[1]) !== false;
  7. $has1in2 = strpos($goal2, $pair[0]) !== false;
  8. $has2in2 = strpos($goal2, $pair[1]) !== false;
  9. // If obj1 has first term and obj2 has second term (or vice versa)
  • gyakutsuki

    not included
  1. // Check if goals contain contradictory terms
  2. foreach ($contradictions as $pair) {
  3. $has1in1 = strpos($goal1, $pair[0]) !== false;
  4. $has2in1 = strpos($goal1, $pair[1]) !== false;
  5. $has1in2 = strpos($goal2, $pair[0]) !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $has2in2 = strpos($goal2, $pair[1]) !== false;
  7. // If obj1 has first term and obj2 has second term (or vice versa)
  8. if (($has1in1 && $has2in2) || ($has2in1 && $has1in2)) {
  9. // Check if they're operating on similar subjects
  • gyakutsuki

    not included
  1. private function generateUserFriendlyErrorMessage(array $errors): string
  2. {
  3. // Check for common error patterns and generate appropriate messages
  4. foreach ($errors as $error) {
  5. // Pattern: "Semantic result missing sources and data"
  6. if (strpos($error, 'Semantic result missing sources and data') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. 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.";
  8. }
  9. // Pattern: "Analytics result missing data"
  10. if (strpos($error, 'Analytics result missing data') !== false) {
  • gyakutsuki

    not included
  1. if (strpos($error, 'Semantic result missing sources and data') !== false) {
  2. 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.";
  3. }
  4. // Pattern: "Analytics result missing data"
  5. if (strpos($error, 'Analytics result missing data') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. 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.";
  7. }
  8. // Pattern: "Hybrid result missing"
  9. if (strpos($error, 'Hybrid result missing') !== false) {
  • gyakutsuki

    not included
  1. // Semantic results MUST have sources OR data, unless it's a valid LLM/memory fallback
  2. if (!$hasSources) {
  3. $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
  4. $isLLMFallback = $hasTextResponse && (
  5. strpos($sourceType, 'llm') !== false ||
  6. strpos($sourceType, 'general knowledge') !== false ||
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. strpos($sourceType, 'conversation') !== false ||
  8. strpos($sourceType, 'memory') !== false
  9. );
  10. if (!$isLLMFallback) {
  • gyakutsuki

    not included
  1. // Semantic results MUST have sources OR data, unless it's a valid LLM/memory fallback
  2. if (!$hasSources) {
  3. $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
  4. $isLLMFallback = $hasTextResponse && (
  5. strpos($sourceType, 'llm') !== false ||
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. strpos($sourceType, 'general knowledge') !== false ||
  7. strpos($sourceType, 'conversation') !== false ||
  8. strpos($sourceType, 'memory') !== false
  9. );
  • gyakutsuki

    not included
  1. $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
  2. $isLLMFallback = $hasTextResponse && (
  3. strpos($sourceType, 'llm') !== false ||
  4. strpos($sourceType, 'general knowledge') !== false ||
  5. strpos($sourceType, 'conversation') !== false ||
  6. strpos($sourceType, 'memory') !== false
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. );
  8. if (!$isLLMFallback) {
  9. $sourcesStatus = isset($finalResult['sources']) ? 'empty' : 'not set';
  10. $dataStatus = isset($finalResult['data']) ? 'empty' : 'not set';
  • gyakutsuki

    not included
  1. if (strpos($error, 'Hybrid result missing') !== false) {
  2. 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.";
  3. }
  4. // Pattern: "Empty response"
  5. if (strpos($error, 'empty') !== false || strpos($error, 'Empty') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. 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.";
  7. }
  8. }
  9. // Default fallback message
  • gyakutsuki

    not included
  1. if (strpos($error, 'Analytics result missing data') !== false) {
  2. 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.";
  3. }
  4. // Pattern: "Hybrid result missing"
  5. if (strpos($error, 'Hybrid result missing') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. 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.";
  7. }
  8. // Pattern: "Empty response"
  9. if (strpos($error, 'empty') !== false || strpos($error, 'Empty') !== false) {
  • gyakutsuki

    not included
  1. if (!$hasSources) {
  2. $sourceType = strtolower($finalResult['source_attribution']['source_type'] ?? '');
  3. $isLLMFallback = $hasTextResponse && (
  4. strpos($sourceType, 'llm') !== false ||
  5. strpos($sourceType, 'general knowledge') !== false ||
  6. strpos($sourceType, 'conversation') !== false ||
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. strpos($sourceType, 'memory') !== false
  8. );
  9. if (!$isLLMFallback) {
  10. $sourcesStatus = isset($finalResult['sources']) ? 'empty' : 'not set';
  • gyakutsuki

    not included
  1. * @return bool
  2. */
  3. private function hasKeyword(string $text, array $keywords): bool
  4. {
  5. foreach ($keywords as $keyword) {
  6. if (strpos($text, $keyword) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. return true;
  8. }
  9. }
  10. return false;
  11. }
  • gyakutsuki

    not included
  1. }
  2. $keywords[] = $entityType;
  3. $keywords[] = str_replace('_', ' ', $entityType);
  4. if (substr($entityType, -3) === 'ies') {
    Consider replacing substr() with str_ends_with() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  5. $keywords[] = substr($entityType, 0, -3) . 'y';
  6. } elseif (substr($entityType, -1) === 's') {
  7. $keywords[] = substr($entityType, 0, -1);
  8. } else {
  9. $keywords[] = $entityType . 's';
  • gyakutsuki

    not included
  1. $keywords[] = $entityType;
  2. $keywords[] = str_replace('_', ' ', $entityType);
  3. if (substr($entityType, -3) === 'ies') {
  4. $keywords[] = substr($entityType, 0, -3) . 'y';
  5. } elseif (substr($entityType, -1) === 's') {
    Consider replacing substr() with str_ends_with() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $keywords[] = substr($entityType, 0, -1);
  7. } else {
  8. $keywords[] = $entityType . 's';
  9. }
  10. }
  • gyakutsuki

    not included
  1. return false;
  2. }
  3. private function hasComments(string $sql): bool
  4. {
  5. return strpos($sql, '--') !== false || strpos($sql, '/*') !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. }
  7. private function hasConsistentData(array $results): bool
  8. {
  9. if (empty($results)) return true;
  • gyakutsuki

    not included
  1. private function evaluateSqlEfficiency(string $sql, array $tablesUsed, string $queryType): float
  2. {
  3. $score = 0.7; // Base score
  4. // Check for SELECT * (inefficient)
  5. if (strpos($sql, 'SELECT *') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $score -= 0.2;
  7. }
  8. // Check for proper indexing hints
  9. if ($this->hasProperIndexing($sql, $tablesUsed)) {
  • gyakutsuki

    not included
  1. $queryWords = explode(' ', strtolower($userQuery));
  2. $sqlLower = strtolower($sql);
  3. $matches = 0;
  4. foreach ($queryWords as $word) {
  5. if (strlen($word) > 3 && strpos($sqlLower, $word) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $matches++;
  7. }
  8. }
  9. return $matches > 0;
  • gyakutsuki

    not included
  1. // Fallback to simple keyword detection if detector fails
  2. $ambiguousTerms = ['best', 'good', 'recent', 'popular', 'top', 'better', 'worse'];
  3. $queryLower = strtolower($query);
  4. foreach ($ambiguousTerms as $term) {
  5. if (strpos($queryLower, $term) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return true;
  7. }
  8. }
  9. return false;
  • gyakutsuki

    not included
  1. }
  2. private function hasProperIndexing(string $sql, array $tables): bool
  3. {
  4. // Check for WHERE clauses that might benefit from indexes
  5. return strpos($sql, 'WHERE') !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. }
  7. private function hasUnnecessaryJoins(string $sql): bool
  8. {
  9. // Count JOINs - more than 5 might be excessive
  • gyakutsuki

    not included
  1. 'HAVING',
  2. 'DISTINCT'
  3. ];
  4. foreach ($slowPatterns as $pattern) {
  5. if (strpos($sqlUpper, $pattern) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return true;
  7. }
  8. }
  9. // Check for multiple JOINs
  • gyakutsuki

    not included
  1. }
  2. private function isWellFormatted(string $sql): bool
  3. {
  4. // Check for basic formatting (line breaks, indentation)
  5. return strpos($sql, "\n") !== false || strpos($sql, "\r") !== false;
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. }
  7. private function hasMeaningfulAliases(string $sql): bool
  8. {
  9. // Check for table aliases that are more than single letters
  • gyakutsuki

    not included
  1. return 'memory';
  2. }
  3. if (strpos($message, 'validation') !== false || strpos($message, 'invalid') !== false) {
  4. return 'validation';
  5. }
  6. if (strpos($message, 'classification') !== false || strpos($message, 'intent') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. return 'classification';
  8. }
  9. if (strpos($message, 'api') !== false || strpos($message, 'gpt') !== false) {
  10. return 'api';
  11. }
  • gyakutsuki

    not included
  1. $message = strtolower($errorMessage);
  2. if (strpos($message, 'database') !== false || strpos($message, 'sql') !== false) {
  3. return 'database';
  4. }
  5. if (strpos($message, 'timeout') !== false || strpos($message, 'time out') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return 'timeout';
  7. }
  8. if (strpos($message, 'memory') !== false) {
  9. return 'memory';
  10. }
  • gyakutsuki

    not included
  1. return 'database';
  2. }
  3. if (strpos($message, 'timeout') !== false || strpos($message, 'time out') !== false) {
  4. return 'timeout';
  5. }
  6. if (strpos($message, 'memory') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. return 'memory';
  8. }
  9. if (strpos($message, 'validation') !== false || strpos($message, 'invalid') !== false) {
  10. return 'validation';
  11. }
  • gyakutsuki

    not included
  1. return 'validation';
  2. }
  3. if (strpos($message, 'classification') !== false || strpos($message, 'intent') !== false) {
  4. return 'classification';
  5. }
  6. if (strpos($message, 'api') !== false || strpos($message, 'gpt') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. return 'api';
  8. }
  9. return 'unknown';
  10. }
  • gyakutsuki

    not included
  1. return 'timeout';
  2. }
  3. if (strpos($message, 'memory') !== false) {
  4. return 'memory';
  5. }
  6. if (strpos($message, 'validation') !== false || strpos($message, 'invalid') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. return 'validation';
  8. }
  9. if (strpos($message, 'classification') !== false || strpos($message, 'intent') !== false) {
  10. return 'classification';
  11. }
  • gyakutsuki

    not included
  1. */
  2. private function categorizeError(string $errorMessage): string
  3. {
  4. $message = strtolower($errorMessage);
  5. if (strpos($message, 'database') !== false || strpos($message, 'sql') !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return 'database';
  7. }
  8. if (strpos($message, 'timeout') !== false || strpos($message, 'time out') !== false) {
  9. return 'timeout';
  10. }
  • gyakutsuki

    not included
  1. $text = strtolower("$reason $comment");
  2. foreach ($keywords as $type => $words) {
  3. foreach ($words as $word) {
  4. if (strpos($text, $word) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  5. return $type;
  6. }
  7. }
  8. }
  • gyakutsuki

    not included
  1. }
  2. }
  3. // Priority 4: Check if rawResult has 'text_response' field (but not if it's the JSON fallback)
  4. if (isset($rawResult['text_response']) && !empty($rawResult['text_response'])) {
  5. if (strpos($rawResult['text_response'], 'Résultat:') === false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return $rawResult['text_response'];
  7. }
  8. }
  9. // Priority 5: Use finalResponse if available (but not if it's the JSON fallback)
  • gyakutsuki

    not included
  1. // If it's an array, search for the response
  2. if (is_array($executionResult)) {
  3. if (isset($executionResult['text_response']) && !empty($executionResult['text_response'])) {
  4. // Check if text_response is NOT the JSON fallback
  5. if (strpos($executionResult['text_response'], 'Résultat:') === false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return $executionResult['text_response'];
  7. }
  8. }
  9. if (isset($executionResult['response']) && !empty($executionResult['response'])) {
  • gyakutsuki

    not included
  1. return $rawResult['text_response'];
  2. }
  3. }
  4. // Priority 5: Use finalResponse if available (but not if it's the JSON fallback)
  5. if (!empty($finalResponse) && strpos($finalResponse, 'Résultat:') === false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return $finalResponse;
  7. }
  8. return '';
  9. }
  • gyakutsuki

    not included
  1. // Fallback to source_table if no name found
  2. if ($docName === null && isset($metadata['source_table'])) {
  3. $tableName = $metadata['source_table'];
  4. // Remove prefix and _embedding suffix
  5. $prefix = defined('CLICSHOPPING_DB_TABLE_PREFIX') ? CLICSHOPPING_DB_TABLE_PREFIX : 'clic_';
  6. if (strpos($tableName, $prefix) === 0) {
    Consider replacing strpos() with str_starts_with() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. $tableName = substr($tableName, strlen($prefix));
  8. }
  9. $tableName = str_replace('_embedding', '', $tableName);
  10. $tableName = str_replace('_', ' ', $tableName);
  11. $docName = ucwords($tableName);
  • gyakutsuki

    not included
  1. return $entityType;
  2. }
  3. // Remove table prefix if present
  4. $prefix = CLICSHOPPING::getConfig('db_table_prefix');
  5. if (!empty($prefix) && strpos($tableName, $prefix) === 0) {
    Consider replacing strpos() with str_starts_with() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $tableName = substr($tableName, strlen($prefix));
  7. }
  8. // Remove '_embedding' suffix if present
  9. $tableName = str_replace('_embedding', '', $tableName);
  • gyakutsuki

    not included
  1. // 🔍 DEBUG: Log prompt loading verification
  2. if ($this->debug) {
  3. error_log("[INFO : ANALYSE] [UnifiedQueryAnalyzer] Prompt Loading Verification:");
  4. error_log(" Prompt length: " . strlen($prompt) . " characters");
  5. error_log(" Prompt preview (first 200 chars): " . substr($prompt, 0, 200) . "...");
  6. error_log(" Query in prompt: " . (strpos($prompt, $query) !== false ? 'YES' : 'NO'));
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. }
  8. // Single GPT call for everything
  9. // Use Gpt::getGptResponse() instead of non-existent complete() method
  • gyakutsuki

    not included
  1. if ($this->debug) {
  2. error_log("UnifiedQueryAnalyzer: Built prompt from language file sections");
  3. error_log("UnifiedQueryAnalyzer: Query to analyze: {$query}");
  4. error_log("UnifiedQueryAnalyzer: Total prompt length: " . strlen($prompt) . " characters");
  5. error_log("UnifiedQueryAnalyzer: Prompt contains query: " . (strpos($prompt, $query) !== false ? 'YES' : 'NO'));
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. }
  7. return $prompt;
  8. }
  • gyakutsuki

    not included
  1. 'as an ai',
  2. 'i\'m an ai'
  3. ];
  4. foreach ($genericPhrases as $phrase) {
  5. if (strpos($response, $phrase) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $validationErrors[] = "Response contains generic LLM phrase indicating lack of knowledge";
  7. return false;
  8. }
  9. }
  • gyakutsuki

    not included
  1. // Check if source type is valid (case-insensitive, partial match)
  2. $sourceType = strtolower($sourceAttr['source_type']);
  3. $isValidSource = false;
  4. foreach ($validSourceTypes as $validType) {
  5. if (strpos($sourceType, strtolower($validType)) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $isValidSource = true;
  7. break;
  8. }
  9. }
  • gyakutsuki

    not included
  1. * @return string Escaped value
  2. */
  3. private function escapeCsvValue(string $value): string
  4. {
  5. // Escape quotes and wrap in quotes if contains comma, quote, or newline
  6. if (strpos($value, ',') !== false || strpos($value, '"') !== false || strpos($value, "\n") !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. return '"' . str_replace('"', '""', $value) . '"';
  8. }
  9. return $value;
  10. }
  • gyakutsuki

    not included
  1. // Simple contradiction check
  2. $s1Lower = strtolower($statement1);
  3. $s2Lower = strtolower($statement2);
  4. // Check for negation patterns
  5. if (strpos($s1Lower, 'not') !== false && strpos($s2Lower, 'not') === false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. return true;
  7. }
  8. return false;
  9. }
  • gyakutsuki

    not included
  1. // Simple keyword matching (replaces deleted PatternAnalysisPattern)
  2. $patternKeywords = ['pattern', 'trend', 'style', 'dominant', 'recurring', 'common'];
  3. $queryLower = strtolower($queryToAnalyze);
  4. foreach ($patternKeywords as $keyword) {
  5. if (strpos($queryLower, $keyword) !== false) {
    Consider replacing strpos() with str_contains() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. if ($this->debug) {
  7. $this->logDebug("Pattern analysis keyword detected: $keyword");
  8. }
  9. return true;
  10. }
  • gyakutsuki

    not included
  1. $table = $matches[1];
  2. }
  3. // Ajouter le préfixe si nécessaire
  4. $prefix = CLICSHOPPING::getConfig('db_prefix');
  5. if (!empty($prefix) && strpos($table, $prefix) !== 0) {
    Consider replacing strpos() with str_starts_with() for improved readability.
    Time to fix: about 1 hour
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  6. $table = $prefix . $table;
  7. }
  8. return trim($table, '`"\'');
  9. }
  • gyakutsuki

    not included

Your project uses legacy callable syntax instead of first-class callable syntax

More information: https://insight.symfony.com/what-we-analyse/php.use_first_class_callable_syntax

  1. // Build a mapping of table names (without prefix) to entity types
  2. $tableToEntityType = [];
  3. foreach ($allTables as $fullTableName) {
  4. $entityType = $registry->getEntityTypeForTable($fullTableName);
  5. // Remove prefix and _embedding suffix to get base table name
  6. $tableName = str_replace([$prefix, '_embedding'], '', $fullTableName);
    Use the first-class callable syntax ($this->method(...))
    Time to fix: about 15 minutes
    Read doc Permalink Copy Prompt
    Last edited by clicshopping
  7. $tableToEntityType[$tableName] = $entityType;
  8. }
  9. // Pattern 1: FROM {table_name}
  10. if (preg_match('/FROM\s+(?:\w+\.)?(\w+)/i', $query, $matches)) {
  • gyakutsuki

    change but there are false posittive