Your project should not commit sensitive files to the repository
- Read doc
- Data leak
- Critical
More information: https://insight.symfony.com/what-we-analyse/git.sensitive_file_committed
-
Core/ClicShopping/External
- vendor
- CommonCurrencies.json
- PasswordHash.php
-
cacert.pem
The sensitive file
cacert.pemis committed to the repository and may expose credentials or private keys. - cert_key_pem_paypal.txt
- update-cacert.sh
Your project uses dangerous command injection functions 16
- Read doc
- Security
- Critical
More information: https://insight.symfony.com/what-we-analyse/php.use_command_injection_function
- }
- if (isset($_POST['download'])) {
- switch ($compress) {
- case 'gzip':
- exec(LOCAL_EXE_GZIP . ' ' . $backup_directory . $backup_file);
- $backup_file .= '.gz';
- break;
- case 'zip':
- exec(LOCAL_EXE_ZIP . ' -j ' . $backup_directory . $backup_file . '.zip ' . $backup_directory . $backup_file);
- unlink($backup_directory . $backup_file);
- case 'gzip':
- exec(LOCAL_EXE_GZIP . ' ' . $backup_directory . $backup_file);
- $backup_file .= '.gz';
- break;
- case 'zip':
- exec(LOCAL_EXE_ZIP . ' -j ' . $backup_directory . $backup_file . '.zip ' . $backup_directory . $backup_file);
- unlink($backup_directory . $backup_file);
- $backup_file .= '.zip';
- }
- header('Content-type: application/x-octet-stream');
- exit;
- } else {
- switch ($compress) {
- case 'gzip':
- exec(LOCAL_EXE_GZIP . ' ' . $backup_directory . $backup_file);
- break;
- case 'zip':
- exec(LOCAL_EXE_ZIP . ' -j ' . $backup_directory . $backup_file . '.zip ' . $backup_directory . $backup_file);
- unlink($backup_directory . $backup_file);
- }
- switch ($compress) {
- case 'gzip':
- exec(LOCAL_EXE_GZIP . ' ' . $backup_directory . $backup_file);
- break;
- case 'zip':
- exec(LOCAL_EXE_ZIP . ' -j ' . $backup_directory . $backup_file . '.zip ' . $backup_directory . $backup_file);
- unlink($backup_directory . $backup_file);
- }
- $CLICSHOPPING_MessageStack->add(CLICSHOPPING::getDef('success_database_saved'), 'success');
- }
- $restore_from = $restore_file;
- $remove_raw = false;
- break;
- case '.gz':
- $restore_from = substr($restore_file, 0, -3);
- exec(LOCAL_EXE_GUNZIP . ' ' . $restore_file . ' -c > ' . $restore_from);
- $remove_raw = true;
- break;
- case 'zip':
- $restore_from = substr($restore_file, 0, -4);
- exec(LOCAL_EXE_UNZIP . ' ' . $restore_file . ' -d ' . $backup_directory);
- exec(LOCAL_EXE_GUNZIP . ' ' . $restore_file . ' -c > ' . $restore_from);
- $remove_raw = true;
- break;
- case 'zip':
- $restore_from = substr($restore_file, 0, -4);
- exec(LOCAL_EXE_UNZIP . ' ' . $restore_file . ' -d ' . $backup_directory);
- $remove_raw = true;
- }
- if (isset($restore_from) && is_file($restore_from) && filesize($restore_from) > 15000) {
- $fd = fopen($restore_from, 'rb');
- 2 => ["pipe", "w"] // stderr
- ];
- $this->logger->info('Starting MCP server process', ['command' => $command]);
- $this->process = proc_open($command, $descriptorspec, $this->pipes);
- if (!is_resource($this->process)) {
- $this->logger->error('Failed to start MCP server process', ['command' => $command]);
- throw new McpConnectionException('Failed to start MCP server process');
- }
- $CLICSHOPPING_Db = Registry::get('Db');
- $Qdate = $CLICSHOPPING_Db->query('select now() as datetime');
- try {
- [$system, $host, $kernel] = preg_split('/[\s,]+/', @exec('uname -a'), 5);
- } catch (\Throwable $e) {
- $system = $host = $kernel = 'unavailable';
- }
- try {
- } catch (\Throwable $e) {
- $system = $host = $kernel = 'unavailable';
- }
- try {
- $uptime = @exec('uptime');
- } catch (\Throwable $e) {
- $uptime = 'unavailable';
- }
- try {
- if (!self::checkExecEnabled()) {
- return false;
- }
- $cmd = 'cd ' . escapeshellarg(self::$root) . ' && composer --no-ansi --no-interaction show 2>/dev/null';
- exec($cmd, $output, $return);
- return $return === 0;
- }
- /**
- if (is_null($library) || !self::checkExecute()) {
- return false;
- }
- $cmd = 'cd ' . escapeshellarg(self::$root) . ' && composer show ' . escapeshellarg($library) . ' 2>/dev/null';
- exec($cmd, $output, $return);
- return $return === 0;
- }
- /**
- * Verifies if the necessary conditions for executing commands are met.
- if (!self::checkExecute() || is_null($library)) {
- return false;
- }
- $cmd = 'cd ' . escapeshellarg(self::$root) . ' && composer show ' . escapeshellarg($library) . ' 2>/dev/null';
- exec($cmd, $output, $return);
- if ($return === 0 && !empty($output)) {
- // Recherche la ligne contenant la version
- foreach ($output as $line) {
- if (str_starts_with($line, 'versions')) {
- if ($library !== null) {
- $cmd .= ' ' . escapeshellarg($library);
- }
- $cmd .= ' 2>&1';
- exec($cmd, $output, $return);
- // Retourne toute la sortie pour plus d'informations, ou une chaîne vide si rien
- return !empty($output) ? implode("\n", $output) : '';
- }
- if (!self::checkExecute() || is_null($library)) {
- return false;
- }
- $cmd = 'cd ' . escapeshellarg(self::$root) . ' && composer require ' . escapeshellarg($library) . ' 2>&1';
- exec($cmd, $output, $return);
- return !empty($output) ? implode("\n", $output) : '';
- }
- /**
- if (!self::checkExecute() || is_null($library)) {
- return '';
- }
- $cmd = 'cd ' . escapeshellarg(self::$root) . ' && composer remove ' . escapeshellarg($library) . ' 2>&1';
- exec($cmd, $output, $return);
- return !empty($output) ? implode("\n", $output) : '';
- }
- /**
- if (!self::checkExecute()) {
- return '';
- }
- $cmd = 'cd ' . escapeshellarg(self::$root) . ' && composer clearcache 2>&1';
- exec($cmd, $output, $return);
- // Retourne toute la sortie pour plus d'informations, ou une chaîne vide si rien
- return !empty($output) ? implode("\n", $output) : '';
- }
- }
Your project uses non-strict array lookups 306
- Read doc
- Reliability
- Major
More information: https://insight.symfony.com/what-we-analyse/php.strict_array_lookup
- */
- public static function checkExecEnabled(): bool
- {
- $disabled = explode(', ', ini_get('disable_functions'));
- return !in_array('exec', $disabled);
- }
- /**
- * Checks if Composer is installed and accessible in the current environment.
- *
- exit;
- }
- // Validate feedback_type
- $validTypes = ['positive', 'negative', 'correction'];
- if (!in_array($input['feedback_type'], $validTypes)) {
- echo json_encode([
- 'success' => false,
- 'error' => 'feedback_type must be one of: ' . implode(', ', $validTypes)
- ]);
- exit;
- $errors = [];
- // ============================================================================
- // 1. Reset Translation Cache
- // ============================================================================
- if (in_array('translations', $cacheTypes)) {
- try {
- $translationCache = new TranslationCache();
- // Count files before
- $cacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Translation/';
- }
- // ============================================================================
- // 3. Reset Classification Cache
- // ============================================================================
- if (in_array('classification', $cacheTypes)) {
- try {
- $classificationCache = new ClassificationCache();
- // Get stats before
- $statsBefore = $classificationCache->getStatistics();
- }
- // ============================================================================
- // 3. Reset Database Query Cache
- // ============================================================================
- if (in_array('database', $cacheTypes)) {
- try {
- $db = Registry::get('Db');
- $prefix = CLICSHOPPING::getConfig('db_table_prefix');
- // Count entries before
- }
- // ============================================================================
- // 4. Reset Schema Query Cache (TASK 5 - ITEM 1)
- // ============================================================================
- if (in_array('schema', $cacheTypes)) {
- try {
- // Count schema cache files before (new location)
- $schemaCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/SchemaQuery/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 5. Reset Intent Classification Cache (TASK 5.1.7.6)
- // ============================================================================
- if (in_array('intent', $cacheTypes)) {
- try {
- // Count intent cache files before (new location - all files)
- $intentCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Intent/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 6. Reset Ambiguity Cache (TASK 4 - Cache Migration)
- // ============================================================================
- if (in_array('ambiguity', $cacheTypes)) {
- try {
- // Count ambiguity cache files before (new location - all files)
- $ambiguityCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Ambiguity/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 7. Reset Translation Ambiguity Cache
- // ============================================================================
- if (in_array('translation_ambiguity', $cacheTypes)) {
- try {
- // Count translation ambiguity cache files before (new location)
- $translationAmbiguityCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Translation/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 8. Reset Context Cache
- // ============================================================================
- if (in_array('context', $cacheTypes)) {
- try {
- // Count context cache files before (new location)
- $contextCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Context/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 8.5. Reset Memory Cache (file-based)
- // ============================================================================
- if (in_array('memory', $cacheTypes)) {
- try {
- $memoryCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Memory/';
- $filesBefore = 0;
- if (is_dir($memoryCacheDir)) {
- }
- // ============================================================================
- // 9. Reset Embedding Cache
- // ============================================================================
- if (in_array('embedding', $cacheTypes)) {
- try {
- // Count embedding cache files before (new location)
- $embeddingCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Embedding/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 10. Reset EmbeddingSearch Cache
- // ============================================================================
- if (in_array('embedding_search', $cacheTypes)) {
- try {
- // Count embedding search cache files before (new location)
- $embeddingSearchCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/EmbeddingSearch/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 11. Reset Hybrid Query Cache (TASK 8: Multi-temporal query caching)
- // ============================================================================
- if (in_array('hybrid', $cacheTypes)) {
- try {
- // Count hybrid cache files before
- $hybridCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Hybrid/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 12. Reset Semantic Query Cache (TASK 8: Multi-temporal query caching)
- // ============================================================================
- if (in_array('semantic', $cacheTypes)) {
- try {
- // Count hybrid cache files before
- $semanticCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Semantic/';
- $filesBefore = 0;
- }
- // ============================================================================
- // 13. Reset Embeddings Cache (PHASE 2 - NewVector cache)
- // ============================================================================
- if (in_array('embeddings', $cacheTypes)) {
- try {
- $embeddingsCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Embeddings/';
- $filesBefore = 0;
- if (is_dir($embeddingsCacheDir)) {
- }
- // ============================================================================
- // 14. Reset SQL Query Cache (PHASE 4)
- // ============================================================================
- if (in_array('sql', $cacheTypes)) {
- try {
- $sqlCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/SQL/';
- $filesBefore = 0;
- if (is_dir($sqlCacheDir)) {
- }
- // ============================================================================
- // 15. Reset Security Cache
- // ============================================================================
- if (in_array('security', $cacheTypes)) {
- try {
- $securityCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Security/';
- $filesBefore = 0;
- if (is_dir($securityCacheDir)) {
- }
- // ============================================================================
- // 16. Reset Reputation Cache
- // ============================================================================
- if (in_array('reputation', $cacheTypes)) {
- try {
- $reputationCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Reputation/';
- $filesBefore = 0;
- if (is_dir($reputationCacheDir)) {
- }
- // ============================================================================
- // 17. Reset Config Cache
- // ============================================================================
- if (in_array('config', $cacheTypes)) {
- try {
- $configCacheDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Work/Cache/Rag/Config/';
- $filesBefore = 0;
- if (is_dir($configCacheDir)) {
- unset($this->storage[$scopedKey]);
- unset($this->metadata[$scopedKey]);
- // Remove from the scope's key list
- $scopeKeys = $this->scopes[$this->currentScope] ?? [];
- $index = array_search($scopedKey, $scopeKeys);
- if ($index !== false) {
- array_splice($this->scopes[$this->currentScope], $index, 1);
- }
- // Use higher priority
- $priorities = ['low' => 1, 'medium' => 2, 'high' => 3, 'critical' => 4];
- $priority1 = $priorities[$obj1->getPriority()];
- $priority2 = $priorities[$obj2->getPriority()];
- $combinedPriority = array_search(max($priority1, $priority2), $priorities);
- // Estimate combined time (not just sum, as there may be synergies)
- $estimatedTime = (int)(($obj1->getEstimatedCompletionTime() + $obj2->getEstimatedCompletionTime()) * 0.8);
- return [
- private function translateMonthName(string $monthName, string $languageCode): string
- {
- $englishMonths = ['January', 'February', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September', 'October', 'November', 'December'];
- $monthIndex = array_search(ucfirst(strtolower($monthName)), $englishMonths);
- if ($monthIndex === false) {
- return $monthName; // Return as-is if not found
- }
- $targetMonths = $this->getMonthNames($languageCode);
- $svg .= "<text x='{$x}' y='{$yLbl}' text-anchor='end' font-size='10' fill='#999' transform='rotate(-35 {$x} {$yLbl})'>{$short}</text>";
- }
- // Marqueur + label sur le pic
- $maxVal = max($values);
- $maxIdx = array_search($maxVal, $values);
- $px = $pts[$maxIdx][0];
- $py = $pts[$maxIdx][1];
- $svg .= "<circle cx='{$px}' cy='{$py}' r='5' fill='#36a2eb' stroke='white' stroke-width='2'/>";
- $labelY = max($padT + 16, $py - 10);
- $svg .= "<text x='{$px}' y='{$labelY}' text-anchor='middle' font-size='12' fill='#36a2eb' font-weight='bold'>{$maxVal}</text>";
- if ($intent === null || !is_array($intent)) {
- return null;
- }
- // Validate required fields
- if (!isset($intent['intent']) || !in_array($intent['intent'], ['price_comparison', 'product_discovery', 'market_research', 'trend_analysis'])) {
- return null;
- }
- // Ensure all fields exist with defaults
- $validatedIntent = [
- ];
- // Validate mode_hint if present
- if ($validatedIntent['mode_hint'] !== null) {
- $validModeHints = ['mode_a', 'mode_b', 'mode_c', 'hybrid'];
- if (!in_array($validatedIntent['mode_hint'], $validModeHints)) {
- $validatedIntent['mode_hint'] = null;
- }
- }
- // Normalize target_site to lowercase
- // Note: For production, this should use ModeSelector's STOPWORDS constant
- // or be externalized to database (v2 improvement)
- $stopWords = ['the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'new', 'official', 'original'];
- $words = explode(' ', $normalized);
- $words = array_filter($words, function($word) use ($stopWords) {
- return !in_array($word, $stopWords) && strlen($word) > 1;
- });
- return implode(' ', $words);
- }
- // Note: For production, this should use ModeSelector's STOPWORDS constant
- // or be externalized to database (v2 improvement)
- $stopWords = ['the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'new', 'official', 'original'];
- $words = explode(' ', $normalized);
- $words = array_filter($words, function($word) use ($stopWords) {
- return !in_array($word, $stopWords) && strlen($word) > 1;
- });
- return implode(' ', $words);
- }
- if ($field === $idColumn) {
- return true;
- }
- // Exclude system timestamp fields
- if (in_array($field, ['created_at', 'updated_at', 'deleted_at'])) {
- return false;
- }
- // Get column type
- $type = $columnTypes[$field] ?? 'string';
- // Get column type
- $type = $columnTypes[$field] ?? 'string';
- // Include numeric columns (for aggregation)
- if (in_array($type, ['int', 'bigint', 'smallint', 'decimal', 'float', 'double'])) {
- return true;
- }
- // Include date/timestamp columns (for temporal analysis)
- if (in_array($type, ['date', 'datetime', 'timestamp', 'time'])) {
- if (in_array($type, ['int', 'bigint', 'smallint', 'decimal', 'float', 'double'])) {
- return true;
- }
- // Include date/timestamp columns (for temporal analysis)
- if (in_array($type, ['date', 'datetime', 'timestamp', 'time'])) {
- return true;
- }
- // Include text columns (for filtering and grouping)
- if (in_array($type, ['varchar', 'char', 'text', 'enum'])) {
- if (in_array($type, ['date', 'datetime', 'timestamp', 'time'])) {
- return true;
- }
- // Include text columns (for filtering and grouping)
- if (in_array($type, ['varchar', 'char', 'text', 'enum'])) {
- return true;
- }
- // Exclude everything else (binary, blob, json, etc.)
- return false;
- // Prefer 'normalized'; fall back to 'normalized_value' for forward-compat
- $scoreDescription = (float) ($factor['normalized'] ?? $factor['normalized_value'] ?? 0.0);
- }
- }
- $finalQuadrant = in_array($quadrant, ['Q1', 'Q2', 'Q3', 'Q4']) ? $quadrant : 'Q_intermediate';
- return [
- 'quadrant' => $finalQuadrant,
- 'score_x' => (float) ($scoreXResult['score'] ?? 0.0),
- 'score_y' => (float) ($scoreYResult['score'] ?? 0.0),
- $fields = DoctrineOrm::getTableColumns($tableName);
- // Exclude only ID and system timestamp fields
- return array_values(array_filter($fields, function($field) use ($idColumn) {
- return $field !== $idColumn
- && !in_array($field, ['created_at', 'updated_at', 'deleted_at']);
- }));
- } catch (\Exception $e) {
- return [];
- }
- $words = preg_split('/[\s,.:;!?"()]+/u', mb_strtolower($onlyText), -1, PREG_SPLIT_NO_EMPTY);
- $grammar = $this->grammar();
- $counts = [];
- foreach ($words as $w) {
- $w = preg_replace('/[^\p{L}\p{N}\-]/u', '', $w);
- if (mb_strlen($w) > 2 && !in_array($w, $grammar)) {
- $counts[$w] = ($counts[$w] ?? 0) + 1;
- }
- }
- arsort($counts);
- $report['wordcountmax'] = array_slice($counts, 0, 8, true);
- $productData = $this->getProductData($productId);
- if ($productData && !$productData['in_stock']) {
- $messages[] = [
- 'type' => 'error',
- 'code' => 'out_of_stock',
- 'param' => '$.line_items[' . array_search($lineItem, $lineItems) . ']',
- 'content_type' => 'plain',
- 'content' => 'Produit ' . $productData['title'] . ' temporairement indisponible'
- ];
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ECOMMERCE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ECOMMERCE_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ECOMMERCE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ECOMMERCE_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ECOMMERCE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ECOMMERCE_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ECOMMERCE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ECOMMERCE_INSTALLED', implode(';', $installed));
- $productsProcessed = $this->processLanguage($currentLanguage);
- $processedCount += $productsProcessed;
- // Move to next language if current is complete
- if ($productsProcessed < $this->batchSize) {
- $currentLanguageIndex = array_search($currentLanguage, array_column($languages, 'languages_id'));
- if ($currentLanguageIndex !== false && isset($languages[$currentLanguageIndex + 1])) {
- $currentLanguage = $languages[$currentLanguageIndex + 1]['languages_id'];
- error_log("[ProcessSeoFaqBatch] Moving to next language: {$currentLanguage}");
- } else {
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_ARCHIVE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_ARCHIVE_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- // make sure no duplicate category IDs exist which could lock the server in a loop
- $tmp_array = [];
- $n = count($cPath_array);
- for ($i = 0; $i < $n; $i++) {
- if (!in_array($cPath_array[$i], $tmp_array)) {
- $tmp_array[] = $cPath_array[$i];
- }
- }
- return $tmp_array;
- $category_name = $this->getCategoryTreeTitle($category['name']);
- $categories_url = $this->getCategoryTreeUrl($category_link);
- if (($this->follow_cpath === true) && in_array($category_id, $this->cpath_array)) {
- $link_title = $this->cpath_start_string . $category_name . $this->cpath_end_string;
- } else {
- $link_title = $category_name;
- }
- $result .= $this->parent_end_string;
- }
- if (isset($this->_data[$category_id]) && (($this->max_level == '0') || ($this->max_level > $level + 1))) {
- if ($this->follow_cpath === true) {
- if (in_array($category_id, $this->cpath_array)) {
- $result .= $this->_buildBranch($category_id, $level + 1);
- }
- } else {
- $result .= $this->_buildBranch($category_id, $level + 1);
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_CATEGORIES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_CATEGORIES_INSTALLED', implode(';', $installed));
- $categories_id = HTML::sanitize($this->Id);
- $new_parent_id = HTML::sanitize($this->moveToCategoryID);
- $path = explode('_', $this->categoriesAdmin->getGeneratedCategoryPathIds($new_parent_id));
- if (\in_array($this->Id, $path)) {
- $CLICSHOPPING_MessageStack->add($this->app->getDef('error_cannot_move_directory_to_parent'), 'error');
- $this->app->redirect('Categories&cPath=' . $this->cPath . '&cID=' . $categories_id);
- } else {
- $sql_array = [
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_MANUFACTURERS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_MANUFACTURERS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CATALOG_PRODUCTS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CATALOG_PRODUCTS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_ATTRIBUTES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_ATTRIBUTES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_SUPPLIERS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_SUPPLIERS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_EMAIL_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_EMAIL_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_NEWSLETTER_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_NEWSLETTER_INSTALLED', implode(';', $installed));
- } else {
- $chosen = [];
- foreach ($_POST['chosen'] as $id) {
- if (is_numeric($id) && !\in_array($id, $chosen)) {
- $chosen[] = $id;
- }
- }
- $ids = array_map(function ($k) {
- }
- } else {
- $chosen = [];
- foreach ($_POST['chosen'] as $id) {
- if (is_numeric($id) && !\in_array($id, $chosen)) {
- $chosen[] = $id;
- }
- }
- $ids = array_map(function ($k) {
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- $allowed = array_map(function ($v) {
- return basename($v, '.php');
- }, glob(CLICSHOPPING::BASE_DIR . 'Apps/Communication/Newsletter/Module/ClicShoppingAdmin/Newsletter/*.php'));
- if (!\in_array($newsletter_module, $allowed)) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_Newsletter->getDef('error_newsletter_module_not_exists'), 'danger');
- $newsletter_error = true;
- }
- if ($newsletters_accept_file == 'on') {
- $allowed = array_map(function ($v) {
- return basename($v, '.php');
- }, glob(CLICSHOPPING::BASE_DIR . 'Apps/Communication/Newsletter/Module/ClicShoppingAdmin/Newsletter/*.php'));
- if (!\in_array($newsletter_module, $allowed)) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_Newsletter->getDef('error_newsletter_module_not_exists'), 'danger');
- $newsletter_error = true;
- }
- if ($newsletters_accept_file == 'on') {
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PAGE_MANAGER_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PAGE_MANAGER_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ADMINISTRATORS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ADMINISTRATORS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- foreach ($Qips as $allowedIp) {
- $ip = $allowedIp['ip'];
- if ($ip === '127.0.0.1' || $ip === 'localhost') {
- if (in_array($clientIp, ['127.0.0.1', '::1'])) {
- self::logSecurityEvent('Localhost access granted', [
- 'api_id' => $api_id,
- 'client_ip' => $clientIp
- ]);
- */
- public static function isLocalEnvironment(): bool
- {
- $ip = HTTP::getIpAddress();
- if (in_array($ip, ['127.0.0.1', '::1'])) {
- return true;
- }
- $serverName = $_SERVER['SERVER_NAME'] ?? '';
- $host = $_SERVER['HTTP_HOST'] ?? '';
- }
- $method = strtoupper($_SERVER["REQUEST_METHOD"]);
- $allowedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];
- if (!in_array($method, $allowedMethods)) {
- throw new Exception("Invalid HTTP method: " . $method);
- }
- return $method;
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_API_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_API_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CACHE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CACHE_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- foreach ($models as $model) {
- $modelId = $model['id'];
- $provider = $model['provider'] ?? 'openai'; // Default to openai if missing
- // Validate provider name
- if (!in_array($provider, $validProviders)) {
- if (defined('CLICSHOPPING_APP_CHATGPT_CH_DEBUG') && CLICSHOPPING_APP_CHATGPT_CH_DEBUG === 'True') {
- error_log("WARNING: Invalid provider '$provider' for model '$modelId'. Using 'openai' as default.");
- }
- $provider = 'openai';
- }
- 'open-mistral-nemo',
- 'open-codestral-mamba',
- 'mistral-moderation-latest'
- ];
- if (empty($model) || !in_array($model, $valid_models)) {
- $model = 'mistral-large-latest';
- }
- $config = new MistralAIChat();
- $config->apiKey = $api_key;
- }
- // Validate type is one of expected values
- if (isset($response['type'])) {
- $validTypes = ['analytics', 'semantic', 'web_search', 'hybrid', 'error', 'clarification'];
- if (!in_array($response['type'], $validTypes)) {
- $warnings[] = "Unexpected type value: {$response['type']}";
- }
- }
- return [
- if ($productData && !$productData['in_stock']) {
- $messages[] = [
- 'type' => 'error',
- 'code' => 'out_of_stock',
- 'text' => 'Produit ' . $productData['title'] . ' temporairement indisponible',
- 'path' => '$.line_items[' . array_search($lineItem, $lineItems) . ']'
- ];
- }
- }
- // Add promotional messages
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CHATGPT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CHATGPT_INSTALLED', implode(';', $installed));
- exit;
- }
- // Validate feedback_type
- $validTypes = ['positive', 'negative', 'correction'];
- if (!in_array($input['feedback_type'], $validTypes)) {
- echo json_encode([
- 'success' => false,
- 'error' => 'feedback_type must be one of: ' . implode(', ', $validTypes)
- ]);
- exit;
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_COUNTRIES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_COUNTRIES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CURRENCY_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CURRENCY_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_LANGUES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_LANGUES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- }
- foreach (glob(CLICSHOPPING::getConfig('dir_root', 'ClicShoppingAdmin') . 'Core/languages/*', GLOB_ONLYDIR) as $dir) {
- $code = basename($dir);
- if (array_search($code, array_column($directories, 'id')) === false) {
- $directories[] = ['id' => $code,
- 'text' => $code
- ];
- }
- }
- }
- foreach (glob(CLICSHOPPING::getConfig('dir_root', 'ClicShoppingAdmin') . 'Core/languages/*', GLOB_ONLYDIR) as $dir) {
- $code = basename($dir);
- if (array_search($code, array_column($directories, 'id')) === false) {
- $directories[] = ['id' => $code,
- 'text' => $code
- ];
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_MODULES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_MODULES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- $module->install();
- $modules_installed = explode(';', \constant($module_key));
- if (!\in_array($class . $file_extension, $modules_installed)) {
- $modules_installed[] = $class . $file_extension;
- }
- Registry::get('Db')->save('configuration', ['configuration_value' => implode(';', $modules_installed)],
- ['configuration_key' => $module_key]
- $module->remove();
- $modules_installed = explode(';', \constant($module_key));
- if (\in_array($class . $file_extension, $modules_installed)) {
- unset($modules_installed[array_search($class . $file_extension, $modules_installed)]);
- }
- Registry::get('Db')->save('configuration', ['configuration_value' => implode(';', $modules_installed)],
- ['configuration_key' => $module_key]
- $module->remove();
- $modules_installed = explode(';', \constant($module_key));
- if (\in_array($class . $file_extension, $modules_installed)) {
- unset($modules_installed[array_search($class . $file_extension, $modules_installed)]);
- }
- Registry::get('Db')->save('configuration', ['configuration_value' => implode(';', $modules_installed)],
- ['configuration_key' => $module_key]
- );
- if ($dir = @dir($module_directory)) {
- while ($file = $dir->read()) {
- if (!is_dir($module_directory . $file)) {
- if (substr($file, strrpos($file, '.')) == $file_extension) {
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- }
- } else {
- if (\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- }
- } else {
- if (\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- } else {
- $new_modules_counter++;
- }
- }
- }
- if (isset($appModuleType)) {
- foreach (Apps::getModules($appModuleType) as $k => $v) {
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- }
- } else {
- if (\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- }
- } else {
- if (\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- } else {
- $new_modules_counter++;
- }
- }
- if ($dir = @dir($module_directory)) {
- while ($file = $dir->read()) {
- if (!is_dir($module_directory . $file)) {
- if (substr($file, strrpos($file, '.')) === $file_extension) {
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- }
- } else {
- if (\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- }
- } else {
- if (\in_array($file, $modules_installed)) {
- $directory_array[] = $file;
- } else {
- $new_modules_counter++;
- }
- }
- }
- if (isset($appModuleType)) {
- foreach (Apps::getModules($appModuleType) as $k => $v) {
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- }
- } else {
- if (\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- if (isset($_GET['list']) && ($_GET['list'] == 'new')) {
- if (!\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- }
- } else {
- if (\in_array($k, $modules_installed)) {
- $directory_array[] = $k;
- } else {
- $new_modules_counter++;
- }
- }
- <tr>
- <td><?php echo $module->title; ?></td>
- <td class="text-start"><?php echo $module->group; ?></td>
- <td class="text-end">
- <?php
- if (\in_array($module->code . $file_extension, $modules_installed) && is_numeric($module->sort_order)) {
- echo $module->sort_order;
- }
- ?>
- </td>
- <td class="text-center">
- $Qcheck = $CLICSHOPPING_Db->get('configuration', 'configuration_value', ['configuration_key' => 'TEMPLATE_BLOCK_GROUPS']);
- if ($Qcheck->fetch() !== false) {
- $tbgroups_array = explode(';', $Qcheck->value('configuration_value'));
- if (!\in_array($module_type, $tbgroups_array)) {
- $tbgroups_array[] = $module_type;
- sort($tbgroups_array);
- $CLICSHOPPING_Db->save('configuration', [
- 'configuration_value' => implode(';', $tbgroups_array),
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ORDERS_STATUS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ORDERS_STATUS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ORDERS_STATUS_INVOICE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ORDERS_STATUS_INVOICE_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PROUCTS_LENGTH_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PROUCTS_LENGTH_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_QUANTITY_UNIT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_QUANTITY_UNIT_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_SETTINGS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_SETTINGS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_TAX_CLASS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_TAX_CLASS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_TAX_GEO_ZONES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_TAX_GEO_ZONES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_TAX_RATES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_TAX_RATES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_TEMPLATE_EMAIL_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_TEMPLATE_EMAIL_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_WEIGHT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_WEIGHT_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ZONES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ZONES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CUSTOMERS_INFO_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CUSTOMERS_INFO_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CUSTOMERS_GDPR_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CUSTOMERS_GDPR_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CUSTOMERS_GROUPS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CUSTOMERS_GROUPS_INSTALLED', implode(';', $installed));
- for ($i = 0, $n = \count($include_modules); $i < $n; $i++) {
- if (str_contains($include_modules[$i]['class'], '\\')) {
- Registry::set('Payment_' . str_replace('\\', '_', $include_modules[$i]['class']), new $include_modules[$i]['file']);
- $module = Registry::get('Payment_' . str_replace('\\', '_', $include_modules[$i]['class']));
- if (($cInfo->customers_group_id != 0) && (\in_array($module->code, $payments_unallowed))) {
- $content .= '<div class="row">';
- $content .= '<div class="col-md-5">';
- $content .= '<div class="form-group row">';
- $content .= '<div class="col-md-12">';
- $content .= '<span class="col-md-1"><i class="bi-check text-success"></i></span>';
- for ($i = 0, $n = \count($include_modules); $i < $n; $i++) {
- if (str_contains($include_modules[$i]['class'], '\\')) {
- Registry::set('Shipping_' . str_replace('\\', '_', $include_modules[$i]['class']), new $include_modules[$i]['file']);
- $module = Registry::get('Shipping_' . str_replace('\\', '_', $include_modules[$i]['class']));
- if (($cInfo->customers_group_id != 0) && (\in_array($module->code, $shipping_unallowed))) {
- $content .= '<div class="col-md-12">';
- $content .= '<span class="col-md-1"><i class="bi-check text-success"></i></span>';
- $content .= '<span class="col-md-3">' . $module->title . '</span>';
- $content .= '</div>';
- } elseif ($cInfo->customers_group_id != 0 && !\in_array($module->code, $shipping_unallowed)) {
- if (($cInfo->customers_group_id != 0) && (\in_array($module->code, $shipping_unallowed))) {
- $content .= '<div class="col-md-12">';
- $content .= '<span class="col-md-1"><i class="bi-check text-success"></i></span>';
- $content .= '<span class="col-md-3">' . $module->title . '</span>';
- $content .= '</div>';
- } elseif ($cInfo->customers_group_id != 0 && !\in_array($module->code, $shipping_unallowed)) {
- $content .= '<div class="col-md-12">';
- $content .= '<span class="col-md-1"><i class="bi-check text-danger"></i></span>';
- $content .= '<span class="col-md-3">' . $module->title . '</span>';
- $content .= '</div>';
- } elseif ($cInfo->customers_group_id == 0) {
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- <div class="form-group row">
- <div class="col-md-12">
- <ul class="list-group-slider list-group-flush">
- <li class="list-group-item-slider">
- <label class="switch">
- <?php echo HTML::checkboxField('payment_unallowed[' . $i . ']', $module->code, (\in_array($module->code, $payments_unallowed)) ? true : false, 'class="success"'); ?>
- <span class="slider"></span>
- </label>
- </li>
- <span class="text-slider"><?php echo $module->title; ?></span>
- </ul>
- <div class="form-group row">
- <div class="col-md-12">
- <ul class="list-group-slider list-group-flush">
- <li class="list-group-item-slider">
- <label class="switch">
- <?php echo HTML::checkboxField('shipping_unallowed[' . $i . ']', $module->code, (\in_array($module->code, $shipping_unallowed)) ? true : false, 'class="success"'); ?>
- <span class="slider"></span>
- </label>
- </li>
- <span class="text-slider"><?php echo $module->title; ?></span>
- </ul>
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CUSTOMERS_MEMBERS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CUSTOMERS_MEMBERS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_REVIEWS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_REVIEWS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_BANNER_MANAGER_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_BANNER_MANAGER_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_FAVORITES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_FAVORITES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_FEATURED_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_FEATURED_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_PRODUCT_RECOMMENDATIONS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_PRODUCT_RECOMMENDATIONS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_SEO_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_SEO_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_SPECIALS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_SPECIALS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_ORDER_TOTAL_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_ORDER_TOTAL_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_ORDER_TOTAL_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_ORDER_TOTAL_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_ORDER_TOTAL_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_ORDER_TOTAL_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_ORDER_TOTAL_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_ORDER_TOTAL_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- {
- if (!$this->isEnabled()) {
- return $this->skip($this->app->getDef('skip_module_disabled'));
- }
- if (!in_array($invoice_status, [self::STATUS_INVOICE, self::STATUS_CANCEL, self::STATUS_CREDIT_NOTE])) {
- return $this->skip($this->app->getDef('skip_status_not_actionable') . ' (' . $invoice_status . ')');
- }
- if ($this->isAlreadySent($order_id)) {
- return $this->skip($this->app->getDef('skip_already_sent') . ' #' . $order_id);
- $msg = $this->app->getDef('error_oauth2_failed') . ' #' . $order_id;
- $this->writeOrderHistory($order_id, '[ERROR] ' . $msg, false);
- return $this->failure($msg);
- }
- $doc_type = in_array($invoice_status, [self::STATUS_CANCEL, self::STATUS_CREDIT_NOTE]) ? self::TYPE_CREDIT_NOTE : self::TYPE_INVOICE;
- $payload = $this->buildPayload($order_id, $customer, $info, $products, $totals, $doc_type);
- if ($payload === null) {
- $msg = $this->app->getDef('error_payload_failed');
- $this->writeOrderHistory($order_id, '[ERROR] ' . $msg, false);
- // Extract totals from the order totals array
- $ht = $tva = $ttc = 0.0;
- foreach ($totals as $t) {
- $val = (float)str_replace(',', '.', preg_replace('/[^0-9.,\-]/', '', strip_tags($t['text'] ?? '0')));
- $c = $t['class'] ?? '';
- if (in_array($c, ['ot_subtotal', 'ST'])) $ht = $val;
- if (in_array($c, ['ot_tax', 'TX'])) $tva = $val;
- if (in_array($c, ['ot_total', 'TO'])) $ttc = $val;
- }
- // Fallback: compute HT from product lines if ot_subtotal not found
- $ht = $tva = $ttc = 0.0;
- foreach ($totals as $t) {
- $val = (float)str_replace(',', '.', preg_replace('/[^0-9.,\-]/', '', strip_tags($t['text'] ?? '0')));
- $c = $t['class'] ?? '';
- if (in_array($c, ['ot_subtotal', 'ST'])) $ht = $val;
- if (in_array($c, ['ot_tax', 'TX'])) $tva = $val;
- if (in_array($c, ['ot_total', 'TO'])) $ttc = $val;
- }
- // Fallback: compute HT from product lines if ot_subtotal not found
- if ($ht == 0.0) {
- foreach ($totals as $t) {
- $val = (float)str_replace(',', '.', preg_replace('/[^0-9.,\-]/', '', strip_tags($t['text'] ?? '0')));
- $c = $t['class'] ?? '';
- if (in_array($c, ['ot_subtotal', 'ST'])) $ht = $val;
- if (in_array($c, ['ot_tax', 'TX'])) $tva = $val;
- if (in_array($c, ['ot_total', 'TO'])) $ttc = $val;
- }
- // Fallback: compute HT from product lines if ot_subtotal not found
- if ($ht == 0.0) {
- foreach ($products as $p) {
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ORDERS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ORDERS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- if ((int)$check['orders_status_invoice'] === $new_invoice_status) {
- return;
- }
- // Only process actionable statuses
- if (!in_array($new_invoice_status, [
- EInvoiceService::STATUS_INVOICE,
- EInvoiceService::STATUS_CANCEL,
- EInvoiceService::STATUS_CREDIT_NOTE,
- ])) {
- return;
- ?>
- <span class="badge bg-success"><?php echo $CLICSHOPPING_Orders->getDef('badge_transmitted'); ?></span>
- <span class="text-success small"><?php echo $CLICSHOPPING_Orders->getDef('text_transmitted_notice'); ?></span>
- <?php
- } elseif (!in_array($current_invoice_status_id, [EInvoiceService::STATUS_INVOICE, EInvoiceService::STATUS_CANCEL, EInvoiceService::STATUS_CREDIT_NOTE])) {
- ?>
- <span class="badge bg-warning text-dark"><?php echo $CLICSHOPPING_Orders->getDef('badge_pending'); ?></span>
- <span class="text-muted small"><?php echo $CLICSHOPPING_Orders->getDef('text_pending_notice'); ?></span>
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_PRODUCTS_RETURN_ORDERS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_PRODUCTS_RETURN_ORDERS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_PAYMENT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_PAYMENT_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_PAYMENT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_PAYMENT_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_PAYMENT_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_PAYMENT_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_STATS_PRODUCTS_NOTIFICATION_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_STATS_PRODUCTS_NOTIFICATION_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_SHIPPING_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_SHIPPING_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_SHIPPING_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_SHIPPING_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- $CLICSHOPPING_Language = Registry::get('Language');
- $module = HTML::sanitize(str_replace(' ', '', $module));
- if (defined('MODULE_ACTION_RECORDER_INSTALLED') && !is_null(MODULE_ACTION_RECORDER_INSTALLED)) {
- if (!is_null($module) && in_array($module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)), explode(';', MODULE_ACTION_RECORDER_INSTALLED))) {
- if (!class_exists($module)) {
- if (is_file($CLICSHOPPING_Template->getModuleDirectory() . '/action_recorder/' . $module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)))) {
- $CLICSHOPPING_Language->loadDefinitions('modules/action_recorder/' . $module);
- include($CLICSHOPPING_Template->getModuleDirectory() . '/action_recorder/' . $module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)));
- } else {
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ACTIONS_RECORDER_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ACTIONS_RECORDER_INSTALLED', implode(';', $installed));
- $modules_array[] = $Qmodules->value('module');
- }
- $expired_entries = 0;
- if (isset($_GET['module']) && \in_array($_GET['module'], $modules_array)) {
- $get_module_class = $CLICSHOPPING_ActionsRecorderClass->getClassModule($_GET['module']);
- if (\is_object($get_module_class)) {
- $expired_entries += $get_module_class->expireEntries();
- } else {
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- echo HTML::form('search', $CLICSHOPPING_ActionsRecorder->link('ActionsRecorder'), 'post', '', ['session_id' => true]);
- echo HTML::selectField('module', $modules_list_array, null, 'onchange="this.form.submit();"');
- ?>
- </span>
- <span class="col-md-1 text-end">
- <?php echo HTML::button($CLICSHOPPING_ActionsRecorder->getDef('button_reset'), null, $CLICSHOPPING_ActionsRecorder->link('ActionsRecorder&Expire' . (isset($_POST['module']) && \in_array($_POST['module'], $modules_array) ? '&module=' . $_POST['module'] : '')), 'danger'); ?>
- </span>
- </div>
- </form>
- </div>
- </div>
- </thead>
- <tbody>
- <?php
- $filter = [];
- if (isset($_POST['module']) && \in_array($_POST['module'], $modules_array)) {
- $filter[] = 'module = :module';
- }
- if (isset($_POST['search']) && !empty($_POST['search'])) {
- $filter[] = 'identifier like :identifier';
- $sql_query .= ' order by date_added desc limit :page_set_offset, :page_set_max_results';
- $Qactions = $CLICSHOPPING_ActionsRecorder->db->prepare($sql_query);
- if (!empty($filter)) {
- if (isset($_POST['module']) && \in_array($_POST['module'], $modules_array)) {
- $Qactions->bindValue(':module', $_POST['module']);
- }
- if (isset($_POST['search']) && !empty($_POST['search'])) {
- $Qactions->bindValue(':identifier', '%' . $_POST['search'] . '%');
- <div class="row">
- <div class="col-md-12">
- <div
- class="col-md-6 float-start pagenumber hidden-xs TextDisplayNumberOfLink"><?php echo $Qactions->getPageSetLabel($CLICSHOPPING_ActionsRecorder->getDef('text_display_number_of_link')); ?></div>
- <div
- class="float-end text-end"> <?php echo $Qactions->getPageSetLinks((isset($_POST['module']) && \in_array($_POST['module'], $modules_array) && \is_object($GLOBALS[$_POST['module']]) ? 'module=' . $_POST['module'] : null) . '&' . (isset($_POST['search']) && !empty($_POST['search']) ? 'search=' . $_POST['search'] : null)); ?></div>
- </div>
- </div>
- </div>
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_ADMINISTRATOR_MENU_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_ADMINISTRATOR_MENU_INSTALLED', implode(';', $installed));
- if (isset($this->Id) && ($this->Id != $this->moveToCategoryID)) {
- $new_parent_id = $this->moveToCategoryID;
- $path = explode('_', AdministratorMenu::getGeneratedAdministratorMenuPathIds($new_parent_id));
- if (\in_array($this->Id, $path)) {
- $CLICSHOPPING_MessageStack->add($this->app->getDef('error_cannot_move_directory_to_parent'), 'error');
- $this->app->redirect('AdministratorMenu&cPath=' . (int)$this->cPath . '&cID=' . (int)$this->Id);
- } else {
- $this->app->db->save('administrator_menu', [
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_APPS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_APPS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_BACKUP_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_BACKUP_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- $dir = dir($backup_directory);
- $contents = [];
- while ($file = $dir->read()) {
- if (!is_dir($backup_directory . $file) && \in_array(substr($file, -3), array('zip', 'sql', '.gz'))) {
- $contents[] = $file;
- }
- }
- sort($contents);
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_CRONJOB_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_CRONJOB_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_DATA_BASE_TABLES_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_DATA_BASE_TABLES_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- ['id' => 'utf8',
- 'text' => $CLICSHOPPING_DataBaseTables->getDef('action_utf8_conversion')
- ]);
- if (isset($_POST['action'])) {
- if (\in_array($_POST['action'], array('check', 'analyze', 'optimize', 'repair', 'utf8'))) {
- if (isset($_POST['id']) && \is_array($_POST['id']) && !empty($_POST['id'])) {
- $tables = Database::getDtTables();
- foreach ($_POST['id'] as $key => $value) {
- if (!\in_array($value, $tables)) {
- if (\in_array($_POST['action'], array('check', 'analyze', 'optimize', 'repair', 'utf8'))) {
- if (isset($_POST['id']) && \is_array($_POST['id']) && !empty($_POST['id'])) {
- $tables = Database::getDtTables();
- foreach ($_POST['id'] as $key => $value) {
- if (!\in_array($value, $tables)) {
- unset($_POST['id'][$key]);
- }
- }
- if (!empty($_POST['id'])) {
- while ($Qaction->fetch()) {
- $table_data[] = [
- ($table != $current_table) ? HTML::outputProtected($table) : '',
- $Qaction->valueProtected('Msg_type'),
- $Qaction->valueProtected('Msg_text'),
- ($table != $current_table) ? HTML::checkboxField('id[]', $table, isset($_POST['id']) && \in_array($table, $_POST['id'])) : ''
- ];
- $current_table = $table;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_DEFINE_LANGUAGE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_DEFINE_LANGUAGE_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- $file_array = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory_selected));
- foreach ($file_array as $filename => $current) {
- $fileInfo = pathinfo($current->getFileName());
- if (array_key_exists('extension', $fileInfo) && in_array($fileInfo['extension'], $fileTypes)) {
- $found[] = $current->getFileName();
- }
- }
- if ($found) { // Check the $found array is not empty
- $file_array = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($filename_selected));
- foreach ($file_array as $filename => $current) {
- $fileInfo = pathinfo($current->getFileName());
- if (array_key_exists('extension', $fileInfo) && in_array($fileInfo['extension'], $fileTypes)) {
- $found[] = $current->getFileName();
- }
- }
- if ($found) { // Check the $found array is not empty
- $file_array = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($template_directory));
- foreach ($file_array as $filename => $current) {
- $fileInfo = pathinfo($current->getFileName());
- if (array_key_exists('extension', $fileInfo) && in_array($fileInfo['extension'], $fileTypes)) {
- $found[] = $current->getFileName();
- }
- }
- if ($found) { // Check the $found array is not empty
- /* if empty error is produced : Fatal error: Uncaught exception 'RuntimeException'*/
- foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($template_directory)) as $filename => $current) {
- $fileInfo = pathinfo($current->getFileName());
- if (array_key_exists('extension', $fileInfo) && \in_array($fileInfo['extension'], $fileTypes)) {
- $found[] = $current->getFileName();
- }
- }
- if ($found) { // Check the $found array is not empty
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_EDIT_DESIGN_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_EDIT_DESIGN_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_EDIT_LOG_ERROR_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_EDIT_LOG_ERROR_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- * @param array $checks An array of check results, each with a 'status' key.
- * @return string The overall status: 'error', 'warning', or 'healthy'.
- */
- private function determineOverallStatus(array $checks): string
- {
- if (in_array('error', array_column($checks, 'status'))) {
- return 'error';
- }
- if (in_array('warning', array_column($checks, 'status'))) {
- return 'warning';
- }
- private function determineOverallStatus(array $checks): string
- {
- if (in_array('error', array_column($checks, 'status'))) {
- return 'error';
- }
- if (in_array('warning', array_column($checks, 'status'))) {
- return 'warning';
- }
- return 'healthy';
- }
- foreach ($Qips as $allowedIp) {
- $ip = $allowedIp['ip'];
- if ($ip === '127.0.0.1' || $ip === 'localhost') {
- if (in_array($clientIp, ['127.0.0.1', '::1'])) {
- self::logSecurityEvent('Localhost access granted', [
- 'mcp_id' => $mcp_id,
- 'client_ip' => $clientIp
- ]);
- */
- public static function isLocalEnvironment(): bool
- {
- $ip = HTTP::getIpAddress();
- if (in_array($ip, ['127.0.0.1', '::1'])) {
- return true;
- }
- $serverName = $_SERVER['SERVER_NAME'] ?? '';
- $host = $_SERVER['HTTP_HOST'] ?? '';
- }
- $method = strtoupper($_SERVER["REQUEST_METHOD"]);
- $allowedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];
- if (!in_array($method, $allowedMethods)) {
- throw new Exception("Invalid HTTP method: " . $method);
- }
- return $method;
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_MCP_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_MCP_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- /**
- * Valide une clé d'API pour un niveau d'accès donné
- */
- public function validateMcpKey(string $mcpKey, string $accessLevel): bool {
- if (!in_array($accessLevel, $this->accessLevels)) {
- return false;
- }
- if (!isset($this->validMcpKeys[$accessLevel])) {
- return false;
- if (!isset($this->validMcpKeys[$accessLevel])) {
- return false;
- }
- return in_array($mcpKey, $this->validMcpKeys[$accessLevel]);
- }
- /**
- * Valide les headers de sécurité requis
- */
- 'ssl_enabled' => $sslEnabled,
- 'origin' => $origin
- ];
- // Add to allowed origins list
- if (!in_array($origin, $this->allowedOrigins)) {
- $this->allowedOrigins[] = $origin;
- }
- }
- // Fallback to localhost if no configurations found
- /**
- * Check if an origin is allowed
- */
- public function isOriginAllowed(string $origin): bool {
- return in_array($origin, $this->allowedOrigins);
- }
- /**
- * Valide une clé d'API pour un niveau d'accès donné
- */
- /**
- * Valide une clé d'API pour un niveau d'accès donné
- */
- public function validateMcpKey(string $mcpKey, string $accessLevel): bool {
- if (!in_array($accessLevel, $this->accessLevels)) {
- return false;
- }
- if (!isset($this->validMcpKeys[$accessLevel])) {
- return false;
- if (!isset($this->validMcpKeys[$accessLevel])) {
- return false;
- }
- return in_array($mcpKey, $this->validMcpKeys[$accessLevel]);
- }
- /**
- * Valide les headers de sécurité requis
- */
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_MODULES_HOOKS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_MODULES_HOOKS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_SEC_DIR_PERMISSIONS_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_SEC_DIR_PERMISSIONS_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- if ($handle = opendir($path)) {
- while (false !== ($filename = readdir($handle))) {
- if (!\in_array($filename, $exclude_array)) {
- $file = ['name' => $path . $filename,
- 'is_dir' => is_dir($path . $filename),
- 'writable' => FileSystem::isWritable($path . $filename)
- ];
- <th
- scope="row"><?php echo substr($file['name'], \strlen(CLICSHOPPING::getConfig('dir_root', 'Shop'))); ?></th>
- <td
- class="text-center"><?php echo $file['writable'] === true ? '<i class="bi-check text-success"></i>' : '<i class="bi bi-x text-danger"></i>'; ?></td>
- <td
- class="text-center"><?php echo(\in_array(substr($file['name'], \strlen(CLICSHOPPING::getConfig('dir_root', 'Shop'))), $whitelist_array) ? '<i class="bi-check text-success"></i>' : '<i class="bi bi-x text-danger"></i>'); ?></td>
- </tr>
- <?php
- }
- }
- ?>
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_SECURITY_CHECK_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_SECURITY_CHECK_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- <?php
- foreach ($modules as $module) {
- $secCheck = $module['instance'];
- if (!\in_array($secCheck->type, $types)) {
- $secCheck->type = 'info';
- }
- $output = '';
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_SERVICE_APP_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_SERVICE_APP_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_UPGRADE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_UPGRADE_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- public function uninstall()
- {
- parent::uninstall();
- $installed = explode(';', MODULE_MODULES_WHOS_ONLINE_INSTALLED);
- $installed_pos = array_search($this->app->vendor . '\\' . $this->app->code . '\\' . $this->code, $installed);
- if ($installed_pos !== false) {
- unset($installed[$installed_pos]);
- $this->app->saveCfgParam('MODULE_MODULES_WHOS_ONLINE_INSTALLED', implode(';', $installed));
- $default_module = $m;
- break;
- }
- }
- $this->page->data['current_module'] = (isset($_GET['module']) && \in_array($_GET['module'], $modules)) ? $_GET['module'] : $default_module;
- }
- }
- continue;
- }
- $fullClass = self::NAMESPACE_PREFIX . $fileInfo->getBasename('.php');
- if (class_exists($fullClass) && in_array(ActionToolsInterface::class, class_implements($fullClass))) {
- try {
- /** @var ActionToolsInterface $toolInstance */
- $toolInstance = new $fullClass();
- $toolName = $toolInstance->getName();
- $this->tools[$toolName] = $fullClass;
- $details_string = preg_replace('/comment\(.+\)$/', '', $details_string);
- $details = array_filter(explode(' ', $details_string), fn($v) => $v !== null && $v !== '');
- $details = array_values($details);
- }
- $is_binary = array_search('binary', $details);
- if (is_int($is_binary)) {
- array_splice($details, $is_binary, 1);
- $schema['col'][$field_name]['binary'] = true;
- }
- if (is_int($is_binary)) {
- array_splice($details, $is_binary, 1);
- $schema['col'][$field_name]['binary'] = true;
- }
- $is_unsigned = array_search('unsigned', $details);
- if (is_int($is_unsigned)) {
- array_splice($details, $is_unsigned, 1);
- $schema['col'][$field_name]['unsigned'] = true;
- }
- if (is_int($is_unsigned)) {
- array_splice($details, $is_unsigned, 1);
- $schema['col'][$field_name]['unsigned'] = true;
- }
- $is_not_null = array_search('not_null', $details);
- if (is_int($is_not_null)) {
- array_splice($details, $is_not_null, 1);
- $schema['col'][$field_name]['not_null'] = true;
- }
- if (is_int($is_not_null)) {
- array_splice($details, $is_not_null, 1);
- $schema['col'][$field_name]['not_null'] = true;
- }
- $is_auto_increment = array_search('auto_increment', $details);
- if (preg_match('/on_update\(([^)]+)\)/', $details_string, $on_update_match)) {
- $schema['col'][$field_name]['on_update'] = $on_update_match[1];
- $details_string = preg_replace('/on_update\([^)]+\)/', '', $details_string);
- $details = array_values(array_filter(explode(' ', $details_string)));
- $needs_quotes = true;
- }
- // Special keywords that don't need quotes
- $keywords = ['CURRENT_TIMESTAMP', 'NULL', 'NOW()', 'CURRENT_DATE', 'CURRENT_TIME'];
- if (in_array(strtoupper($default_value), $keywords)) {
- $needs_quotes = false;
- }
- // Add DEFAULT clause
- if ($needs_quotes && !in_array(strtoupper($default_value), $keywords)) {
- if (in_array(strtoupper($default_value), $keywords)) {
- $needs_quotes = false;
- }
- // Add DEFAULT clause
- if ($needs_quotes && !in_array(strtoupper($default_value), $keywords)) {
- $row .= " DEFAULT '" . addslashes($default_value) . "'";
- } else {
- $row .= ' DEFAULT ' . $default_value;
- }
- }
- $this->result = $this->cache_data;
- } else {
- $fetch_argument = $args[0] ?? null;
- $ctor_args = $args[1] ?? [];
- if (in_array($fetch_style, [PDO::FETCH_COLUMN])) {
- $this->result = parent::fetchAll($fetch_style, $fetch_argument);
- } elseif (in_array($fetch_style, [PDO::FETCH_CLASS, PDO::FETCH_FUNC])) {
- $this->result = parent::fetchAll($fetch_style, $fetch_argument, $ctor_args);
- } else {
- $this->result = parent::fetchAll($fetch_style);
- $fetch_argument = $args[0] ?? null;
- $ctor_args = $args[1] ?? [];
- if (in_array($fetch_style, [PDO::FETCH_COLUMN])) {
- $this->result = parent::fetchAll($fetch_style, $fetch_argument);
- } elseif (in_array($fetch_style, [PDO::FETCH_CLASS, PDO::FETCH_FUNC])) {
- $this->result = parent::fetchAll($fetch_style, $fetch_argument, $ctor_args);
- } else {
- $this->result = parent::fetchAll($fetch_style);
- }
- */
- public function setExcludeEntries(?array $entries)
- {
- if (is_array($entries)) {
- foreach ($entries as $value) {
- if (!in_array($value, $this->exclude_entries)) {
- $this->exclude_entries[] = $value;
- }
- }
- } elseif (is_string($entries)) {
- if (!in_array($entries, $this->exclude_entries)) {
- if (!in_array($value, $this->exclude_entries)) {
- $this->exclude_entries[] = $value;
- }
- }
- } elseif (is_string($entries)) {
- if (!in_array($entries, $this->exclude_entries)) {
- $this->exclude_entries[] = $entries;
- }
- }
- }
- $this->listing = array();
- }
- if ($dir = @dir($directory)) {
- while (($entry = $dir->read()) !== false) {
- if (!in_array($entry, $this->exclude_entries)) {
- if (($this->include_files === true) && is_file($dir->path . DIRECTORY_SEPARATOR . $entry)) {
- if (empty($this->check_extension) || in_array(mb_strtolower(substr($entry, strrpos($entry, '.') + 1)), $this->check_extension)) {
- if ($this->adddirectory_to_filename === true) {
- if ($dir->path !== $this->directory) {
- $entry = substr($dir->path, strlen($this->directory) + 1) . DIRECTORY_SEPARATOR . $entry;
- if ($dir = @dir($directory)) {
- while (($entry = $dir->read()) !== false) {
- if (!in_array($entry, $this->exclude_entries)) {
- if (($this->include_files === true) && is_file($dir->path . DIRECTORY_SEPARATOR . $entry)) {
- if (empty($this->check_extension) || in_array(mb_strtolower(substr($entry, strrpos($entry, '.') + 1)), $this->check_extension)) {
- if ($this->adddirectory_to_filename === true) {
- if ($dir->path !== $this->directory) {
- $entry = substr($dir->path, strlen($this->directory) + 1) . DIRECTORY_SEPARATOR . $entry;
- }
- }
- * @param string $type The type of the module to check for.
- * @return bool Returns true if the module exists, false otherwise.
- */
- final public function hasModule(string $module, string $type): bool
- {
- return isset($this->modules[$type]) && in_array($module, $this->modules[$type]);
- }
- /**
- * Sets the app information by reflecting the current class and loading data
- * from a metafile. Assigns the app's code, vendor, title, version, and modules
- $flags['session_id'] = false;
- }
- // Security: Validate method against whitelist
- $allowed_methods = ['post', 'get'];
- $safe_method = in_array(strtolower($method ?? 'post'), $allowed_methods) ? strtolower($method) : 'post';
- // Security: Sanitize form action URL
- $safe_action = static::sanitizeUrl($action);
- $form = '<form name="' . static::outputProtected($name) . '" action="' . $safe_action . '" method="' . $safe_method . '"';
- $field .= ' id="' . static::output(substr($parameters, $offset + 4, strpos($parameters, '"', $offset + 4) - ($offset + 4))) . '_' . $counter . '"';
- }
- $field .= ' value="' . static::output($selection_value) . '"';
- if (isset($default) && (($default === true) || (!is_array($default) && ((string)$default == (string)$selection_value)) || (is_array($default) && in_array($selection_value, $default)))) {
- $field .= ' checked="checked"';
- }
- if (!empty($parameters)) {
- $field .= ' ' . $parameters;
- if (!isset($params['type'])) {
- $params['type'] = 'submit';
- }
- if (!in_array($params['type'], $types)) {
- $params['type'] = 'submit';
- }
- if (($params['type'] == 'submit') && isset($link)) {
- $params['type'] = 'button';
- if (($params['type'] == 'submit') && isset($link)) {
- $params['type'] = 'button';
- }
- if (isset($style) && !in_array($style, $styles)) {
- unset($style);
- }
- if (isset($size) && !in_array($size, $size_button)) {
- unset($size);
- if (isset($style) && !in_array($style, $styles)) {
- unset($style);
- }
- if (isset($size) && !in_array($size, $size_button)) {
- unset($size);
- }
- $button = '';
- if (!isset($data['cafile'])) {
- $data['cafile'] = CLICSHOPPING::BASE_DIR . 'External/cacert.pem';
- }
- if (isset($data['format']) && !in_array($data['format'], ['json'])) {
- trigger_error('HttpRequest::getResponse(): Unknown "format": ' . $data['format']);
- unset($data['format']);
- }
- ];
- $domain = strtolower(substr(strrchr($email, "@"), 1));
- if (in_array($domain, $temp_domains)) {
- return true;
- }
- }
- return false;
- $stack = [
- 'text' => $message,
- 'type' => $type
- ];
- if (!$this->exists($group) || !in_array($stack, $this->data[$group])) {
- $this->data[$group][] = $stack;
- }
- }
- /**
- protected function validateExtension(string $filename): bool
- {
- $extension = mb_strtolower(substr($filename, strrpos($filename, '.') + 1));
- // Check against dangerous extensions
- if (in_array($extension, $this->_dangerousExtensions)) {
- return false;
- }
- // If specific extensions are configured, check against them
- if (!empty($this->_extensions)) {
- return false;
- }
- // If specific extensions are configured, check against them
- if (!empty($this->_extensions)) {
- return in_array($extension, $this->_extensions);
- }
- return true;
- }
- public function isInstalled()
- {
- $module = HTML::sanitize(str_replace(' ', '', $this->_module));
- if (defined('MODULE_ACTION_RECORDER_INSTALLED') && !is_null(MODULE_ACTION_RECORDER_INSTALLED)) {
- if (!is_null($module) && \in_array($module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)), explode(';', MODULE_ACTION_RECORDER_INSTALLED))) {
- if (!class_exists($module)) {
- if (is_file(CLICSHOPPING::getConfig('dir_root', 'Shop') . 'Core/modules/action_recorder/' . $module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)))) {
- $this->lang->loadDefinitions('Shop/Module/ActionRecorder/' . $module);
- $name = (($key) ? 'configuration[' . $key . ']' : 'configuration_value');
- foreach ($contents as $item) {
- $fileInfo = pathinfo($item);
- if (array_key_exists('extension', $fileInfo) && \in_array($fileInfo['extension'], $fileTypes)) {
- $found[] = $item;
- }
- }
- if ($found) { // Check the $found array is not empty
- sort($select_array);
- $values_array = explode(';', $values);
- $output = '';
- foreach ($select_array as $file) {
- $output .= HTML::checkboxField('ht_datepicker_jquery_file[]', $file, \in_array($file, $values_array)) . ' ' . HTML::outputProtected($file) . '<br />';
- }
- if (!empty($output)) {
- $output = '<br />' . substr($output, 0, -6);
- }
- $Qproducts->bindInt(':language_id', (int)$CLICSHOPPING_Language->getId());
- $Qproducts->execute();
- while ($Qproducts->fetch()) {
- if (MODE_B2B_B2C == 'True') {
- if (!in_array($Qproducts->valueInt('products_id'), $exclude)) {
- $Qprice = $CLICSHOPPING_Db->prepare('select customers_group_price,
- customers_group_id
- from :table_products_groups
- where products_id = :products_id
- $price_string = '';
- $sde = 0;
- //while(list($sdek,$sdev)=each($all_groups)){
- foreach ($all_groups as $sdek => $sdev) {
- if (!in_array($Qproducts->valueInt('products_id') . ":" . (int)$sdek, $exclude)) {
- if ($sde)
- $price_string .= ' - ';
- $price_string .= $sdev . ' : ' . $CLICSHOPPING_Currencies->format(isset($product_prices[$sdek]) ? $product_prices[$sdek] : $Qproducts->valueDecimal('products_price'));
- $sde = 1;
- }
- // Ajouter VISITOR_NAME . ': ' . $CLICSHOPPING_Currencies->format($Qproducts->valueDecimal('products_price')) pour permettre d'afficher le prix des clients qui ne font pas partie d'un groupe B2B(
- $select_string .= '<option value="' . $Qproducts->valueInt('products_id') . '">' . HTML::outputProtected($Qproducts->value('products_name')) . ' (' . CLICSHOPPING::getDef('visitor_name') . ': ' . $CLICSHOPPING_Currencies->format($Qproducts->valueDecimal('products_price')) . ' - ' . $price_string . ')</option>';
- }
- } else {
- if (!in_array($Qproducts->valueInt('products_id'), $exclude)) {
- $select_string .= '<option value="' . $Qproducts->valueInt('products_id') . '">' . HTML::outputProtected($Qproducts->value('products_name')) . ' (' . $CLICSHOPPING_Currencies->format($Qproducts->valueDecimal('products_price')) . ')</option>';
- }
- }
- // ####### END #######
- {
- if (is_dir($source) === true) {
- $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::CHILD_FIRST);
- foreach ($files as $file) {
- if (in_array($file->getBasename(), array('.', '..')) !== true) {
- if ($file->isDir() === true) {
- rmdir($file->getPathName());
- } elseif (($file->isFile() === true) || ($file->isLink() === true)) {
- unlink($file->getPathname());
- }
- $fileTypes = ['php']; // Create an array of file types
- $found = []; // Traverse the folder, and add filename to $found array if type matches
- foreach ($contents as $item) {
- $fileInfo = pathinfo($item);
- if (array_key_exists('extension', $fileInfo) && in_array($fileInfo['extension'], $fileTypes)) {
- $found[] = $item;
- }
- }
- if ($found) { // Check the $found array is not empty
- $QpaymentsNotAllowed->execute();
- $payments_not_allowed = $QpaymentsNotAllowed->fetch();
- $payments_unallowed = explode(",", $payments_not_allowed['group_payment_unallowed']);
- $clearance = (in_array($pay_check, $payments_unallowed)) ? true : false;
- } elseif ($CLICSHOPPING_Customer->isLoggedOn()) {
- $clearance = true;
- } else {
- $clearance = false;
- $Qpayments->execute();
- $payments_not_allowed = $Qpayments->fetch();
- $payments_unallowed = explode(",", $payments_not_allowed['group_payment_unallowed']);
- $clearance = (!in_array($pay_check, $payments_unallowed)) ? true : false;
- return $clearance;
- }
- }
- $QshippingNotAllowed->execute();
- $shipping_not_allowed = $QshippingNotAllowed->fetch();
- $shipping_unallowed = explode(",", $shipping_not_allowed['group_shipping_unallowed']);
- $shipping_clearance = (in_array($shipping_check, $shipping_unallowed)) ? true : false;
- } elseif ($CLICSHOPPING_Customer->isLoggedOn()) {
- $shipping_clearance = true;
- } else {
- $shipping_clearance = false;
- }
- $shipping_not_allowed = $Qshipping->fetch();
- if (!empty($shipping_not_allowed['group_payment_unallowed'])) {
- $shipping_unallowed = explode(',', $shipping_not_allowed['group_payment_unallowed']);
- $shipping_clearance = (!in_array($shipping_check, $shipping_unallowed)) ? true : false;
- } else {
- $shipping_clearance = false;
- }
- return $shipping_clearance;
- $string = '';
- if (is_array($array) && !empty($array)) {
- foreach ($array as $key => $value) {
- if (!in_array($key, $exclude)) {
- $string .= $key . '=' . $value . '&';
- }
- }
- $string = substr($string, 0, -1);
- $Qglobal->execute();
- $global = $Qglobal->fetch();
- if (isset($_POST['action']) && ($_POST['action'] == 'process') && isset($_POST['formid']) && ($_POST['formid'] === $_SESSION['sessiontoken'])) {
- if (isset($_POST['product_global']) && is_numeric($_POST['product_global']) && in_array($_POST['product_global'], ['0', '1'])) {
- $product_global = (int)$_POST['product_global'];
- } else {
- $product_global = 0;
- }
- } elseif (count($products) > 0) {
- $products_parsed = [];
- foreach ($products as $value) {
- if (is_numeric($value) && !in_array($value, $products_parsed)) {
- $products_parsed[] = $value;
- }
- }
- if (count($products_parsed) > 0) {
- if (defined('MODULE_PAYMENT_INSTALLED') && !is_null(MODULE_PAYMENT_INSTALLED)) {
- $this->modules = explode(';', MODULE_PAYMENT_INSTALLED);
- $include_modules = [];
- if ((!is_null($module)) && (in_array($module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)), $this->modules, true) || in_array($module, $this->modules))) {
- $this->selected_module = $module;
- if (str_contains($module, '\\')) {
- $class = Apps::getModuleClass($module, 'Payment');
- if (($this->getCountPaymentModules() == 1) && (!isset($_SESSION['payment']) || ($_SESSION['payment'] != $include_modules[0]['class']))) {
- $_SESSION['payment'] = $include_modules[0]['class'];
- }
- if ((!is_null($module)) && (in_array($module . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)), $this->modules, true) || in_array($module, $this->modules))) {
- if (str_contains($module, '\\')) {
- $CLICSHOPPING_PM = Registry::get('Payment_' . str_replace('\\', '_', $module));
- if (isset($CLICSHOPPING_PM->form_action_url)) {
- /**
- $code = $vendor . '\\' . $app . '\\' . $module;
- }
- }
- if (isset($code) && (in_array($code . '.' . substr(CLICSHOPPING::getIndex(), (strrpos(CLICSHOPPING::getIndex(), '.') + 1)), $this->modules) || in_array($code, $this->modules))) {
- if (str_contains($code, '\\')) {
- $class = Apps::getModuleClass($code, 'Shipping');
- $include_modules[] = [
- 'class' => $code,
- include($this->_directoryIncludes . $this->_directoryModules . $group . DIRECTORY_SEPARATOR . $class . '.php');
- }
- }
- // exclude $modules_boxe and search if the modules exist
- if (is_numeric(array_search($group, $this->getReadModulesDefaultDirectories())) && $group != $modules_boxes) {
- $result = array_search($group, $this->getReadModulesDefaultDirectories());
- if (!is_null($result)) {
- if (is_file($this->getPathDirectoryTemplateThema() . $this->_directoryModules . $group . DIRECTORY_SEPARATOR . $class . '.php')) {
- include($this->getPathDirectoryTemplateThema() . $this->_directoryModules . $group . DIRECTORY_SEPARATOR . $class . '.php');
- }
- }
- // exclude $modules_boxe and search if the modules exist
- if (is_numeric(array_search($group, $this->getReadModulesDefaultDirectories())) && $group != $modules_boxes) {
- $result = array_search($group, $this->getReadModulesDefaultDirectories());
- if (!is_null($result)) {
- if (is_file($this->getPathDirectoryTemplateThema() . $this->_directoryModules . $group . DIRECTORY_SEPARATOR . $class . '.php')) {
- include($this->getPathDirectoryTemplateThema() . $this->_directoryModules . $group . DIRECTORY_SEPARATOR . $class . '.php');
- } elseif (is_file($this->getDefaultTemplateDirectory() . DIRECTORY_SEPARATOR . $this->_directoryModules . $group . DIRECTORY_SEPARATOR . $class . '.php')) {
- $currentParent = $newParentId;
- $visitedCategories = [];
- // Traverse up the parent chain to check for circular reference
- while ($currentParent !== 0) {
- if (in_array($currentParent, $visitedCategories)) {
- return true; // Already visited, indicates circular reference
- }
- if ($currentParent === $categoryId) {
- return true; // Found the original category in the parent chain
- // Validate numeric fields
- if (isset($data['suppliers_country_id']) && !is_numeric($data['suppliers_country_id'])) {
- $errors[] = 'Country ID must be numeric';
- }
- if (isset($data['suppliers_status']) && !in_array($data['suppliers_status'], [0, 1])) {
- $errors[] = 'Supplier status must be 0 or 1';
- }
- if (isset($data['languages_id']) && !is_numeric($data['languages_id'])) {
- $errors[] = 'Language ID must be numeric';
- while ($file = $dir->read()) {
- if (!is_dir($backup_directory . $file)) {
- $ext = substr($file, strrpos($file, '.') + 1);
- if (in_array($ext, ['zip', 'sql', 'gz']) && !isset($contents[$ext])) {
- $contents[$ext] = $file;
- if ($ext !== 'sql') { // zip and gz (binaries) prioritised over sql (plain text)
- break;
- }
- }
- } else {
- $products_attributes_image = '';
- }
- $checked = \is_array($selected_attributes) && \in_array($value['id'], $selected_attributes) ? ' checked' : '';
- $chk_id = 'chk_' . $QproductsOptionsName->valueInt('products_options_id') . '_' . $value['id'];
- $products_options_content_display .= '<div class="col-md-12">';
- $products_options_content_display .= '<span class="ModuleProductsInfoOptionsPullDownMenu">';
- $products_options_content_display .= '<div class="custom-control custom-checkbox">';
- foreach ($dir_content as $key => $content) {
- $path = $root_dir . DIRECTORY_SEPARATOR . $content;
- if (is_file($path) && is_readable($path)) {
- // skip ignored files
- if (!\in_array($content, $ignore_files)) {
- if (preg_match($ignore_regex, $content) == 0) {
- $content_chunks = explode(".", $content);
- $ext = $content_chunks[\count($content_chunks) - 1];
- // only include files with desired extensions
- if (\in_array($ext, $allow_extensions)) {
- if (!\in_array($content, $ignore_files)) {
- if (preg_match($ignore_regex, $content) == 0) {
- $content_chunks = explode(".", $content);
- $ext = $content_chunks[\count($content_chunks) - 1];
- // only include files with desired extensions
- if (\in_array($ext, $allow_extensions)) {
- // save file name with path
- $all_data[] = $path;
- }
- }
- }
- }
- }
- } // if content is a directory and readable, add path and name
- elseif (is_dir($path) && is_readable($path)) {
- // skip any ignored dirs
- if (!\in_array($content, $ignore_dirs)) {
- // recursive callback to open new directory
- $all_data = get_files($path, $all_data);
- }
- }
- } // end foreach
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
- } catch (Exception $e) {
- if ($secure === true) {
- throw $e;
- }
- $result = mt_rand($min, $max);
- }
- return $result;
- }
Your project should not contain PHP files defining multiple classes 2
- Read doc
- Productivity
- Info
More information: https://insight.symfony.com/what-we-analyse/php.file_contains_more_than_one_class
Your project should use dedicated PHP string functions 202
- Read doc
- Productivity
- Info
More information: https://insight.symfony.com/what-we-analyse/php.use_string_function
- // Check if column type is VECTOR (cannot have empty string default)
- $is_vector_type = preg_match('/^vector/i', $columnType);
- // Check if default value is already quoted (starts and ends with single quote)
- $is_already_quoted = (strlen($default_value) >= 2 &&
- substr($default_value, 0, 1) === "'" &&
- substr($default_value, -1) === "'");
- // Skip empty string defaults for numeric types (invalid SQL)
- if ($is_numeric_type && $default_value === '') {
- // Don't add default clause - let MySQL use its default behavior
- $is_vector_type = preg_match('/^vector/i', $columnType);
- // Check if default value is already quoted (starts and ends with single quote)
- $is_already_quoted = (strlen($default_value) >= 2 &&
- substr($default_value, 0, 1) === "'" &&
- substr($default_value, -1) === "'");
- // Skip empty string defaults for numeric types (invalid SQL)
- if ($is_numeric_type && $default_value === '') {
- // Don't add default clause - let MySQL use its default behavior
- } elseif ($is_datetime_type && $default_value === '') {
- $schema .= 'NULL, ';
- } elseif (!\is_null($Qrows->value($i))) {
- $row = $Qrows->value($i);
- // Check if this is a VECTOR column
- if (isset($columnTypes[$i]) && strpos(strtolower($columnTypes[$i]), 'vector') !== false) {
- // VECTOR data is already in the correct format from MariaDB
- // Just escape it properly
- $row = addslashes($row);
- } else {
- $row = addslashes($row);
- glob($oldCacheDir . 'Rag_Embedding_*.cache'),
- glob($oldCacheDir . 'embedding_*.cache')
- );
- // Exclude embedding_search files
- $oldFiles = array_filter($oldFiles, function($file) {
- return strpos(basename($file), 'embedding_search_') !== 0;
- });
- $filesBefore += count($oldFiles);
- // Delete old embedding cache files
- foreach ($oldFiles as $file) {
- $oldFiles = array_merge(
- glob($oldCacheDir . 'Rag_Embedding_*.cache'),
- glob($oldCacheDir . 'embedding_*.cache')
- );
- $oldFiles = array_filter($oldFiles, function($file) {
- return strpos(basename($file), 'embedding_search_') !== 0;
- });
- $filesAfter += count($oldFiles);
- }
- $results['embedding'] = $filesBefore - $filesAfter;
- $oldFiles = array_merge(
- glob($oldCacheDir . 'Rag_Embedding_*.cache'),
- glob($oldCacheDir . 'embedding_*.cache')
- );
- $oldFiles = array_filter($oldFiles, function($file) {
- return strpos(basename($file), 'embedding_search_') !== 0;
- });
- $filesBefore += count($oldFiles);
- foreach ($oldFiles as $file) {
- @unlink($file);
- }
- $oldFilesAfter = array_merge(
- glob($oldCacheDir . 'Rag_Embedding_*.cache'),
- glob($oldCacheDir . 'embedding_*.cache')
- );
- $oldFilesAfter = array_filter($oldFilesAfter, function($file) {
- return strpos(basename($file), 'embedding_search_') !== 0;
- });
- $filesAfter += count($oldFilesAfter);
- }
- $results['embeddings'] = $filesBefore - $filesAfter;
- error_log('[WebSearchFormatter] Formatting web search results\n');
- error_log('[WebSearchFormatter] Result keys: ' . implode(', ', array_keys($results)) . "\n");
- error_log('[WebSearchFormatter] Has text_response: ' . (isset($results['text_response']) ? 'YES' : 'NO') . "\n");
- if (isset($results['text_response'])) {
- $isHtml = (strpos($results['text_response'], '<') !== false);
- error_log('[WebSearchFormatter] text_response is HTML: ' . ($isHtml ? 'YES' : 'NO') . "\n");
- error_log('[WebSearchFormatter] text_response length: ' . strlen($results['text_response']) . "\n");
- }
- }
- $isHtmlContent = false;
- if (isset($results['text_response']) && !empty($results['text_response'])) {
- $interpretationText = $results['text_response'];
- // Check if text_response contains HTML (from ResultSynthesizer)
- $isHtmlContent = (strpos($interpretationText, '<div') !== false || strpos($interpretationText, '<p>') !== false);
- } elseif (isset($results['interpretation']) && $results['interpretation'] !== 'Array') {
- $interpretationText = $results['interpretation'];
- } elseif (isset($results['response']) && !empty($results['response'])) {
- $interpretationText = $results['response'];
- }
- * @param string $ip The IP address to check
- * @param string $range The CIDR range (e.g., '
- */
- public static function ipInRange(string $ip, string $range): bool
- {
- if (strpos($range, '/') === false) {
- return $ip === $range;
- }
- list($subnet, $bits) = explode('/', $range);
- $ip = ip2long($ip);
- {
- $params = [];
- // Model-specific parameter mapping
- // GPT-4o-mini, GPT-4.1 series, GPT-5 series use max_completion_tokens
- if (strpos($model, 'gpt-4.1-mini') === 0 ||
- strpos($model, 'gpt-4.1') === 0 ||
- strpos($model, 'gpt-5') === 0) {
- $params['max_completion_tokens'] = $maxtoken;
- } else {
- // Default for GPT-4o, Anthropic, Mistral, LM Studio, and other models
- $params = [];
- // Model-specific parameter mapping
- // GPT-4o-mini, GPT-4.1 series, GPT-5 series use max_completion_tokens
- if (strpos($model, 'gpt-4.1-mini') === 0 ||
- strpos($model, 'gpt-4.1') === 0 ||
- strpos($model, 'gpt-5') === 0) {
- $params['max_completion_tokens'] = $maxtoken;
- } else {
- // Default for GPT-4o, Anthropic, Mistral, LM Studio, and other models
- $params['max_tokens'] = $maxtoken;
- // Model-specific parameter mapping
- // GPT-4o-mini, GPT-4.1 series, GPT-5 series use max_completion_tokens
- if (strpos($model, 'gpt-4.1-mini') === 0 ||
- strpos($model, 'gpt-4.1') === 0 ||
- strpos($model, 'gpt-5') === 0) {
- $params['max_completion_tokens'] = $maxtoken;
- } else {
- // Default for GPT-4o, Anthropic, Mistral, LM Studio, and other models
- $params['max_tokens'] = $maxtoken;
- }
- $models = self::getGptModel();
- foreach ($models as $modelInfo) {
- if ($modelInfo['id'] === $model) {
- // Check if this is a GPT-5 series model (uses reasoning API)
- if (strpos($modelInfo['id'], 'gpt-5') === 0) {
- return true;
- }
- return false;
- }
- return false;
- }
- }
- // Model not found in list - check by prefix as fallback
- return strpos($model, 'gpt-5') === 0;
- }
- /**
- * Get model context length limit
- *
- $module_key = $CLICSHOPPING_CfgModule->get($set, 'key');
- $appModuleType = $CLICSHOPPING_ModulesAdmin->getSwitchModules($module_type);
- if (strpos($_GET['module'], '\\') !== false) {
- $class = Apps::getModuleClass($_GET['module'], $appModuleType);
- if (class_exists($class)) {
- $file_extension = '';
- $module = new $class();
- $modules_payment = explode(';', $Qconfiguration_payment->value('configuration_value'));
- $include_modules = [];
- foreach ($modules_payment as $value) {
- if (strpos($value, '\\') !== false) {
- $class = Apps::getModuleClass($value, 'Payment');
- $include_modules[] = ['class' => $value,
- 'file' => $class
- ];
- ];
- }
- }
- for ($i = 0, $n = \count($include_modules); $i < $n; $i++) {
- if (strpos($include_modules[$i]['class'], '\\') !== false) {
- Registry::set('Payment_' . str_replace('\\', '_', $include_modules[$i]['class']), new $include_modules[$i]['file']);
- $module = Registry::get('Payment_' . str_replace('\\', '_', $include_modules[$i]['class']));
- ?>
- <div class="row">
- <div class="col-md-12">
- $modules_shipping = explode(';', $Qconfiguration_shipping->value('configuration_value'));
- $include_modules = [];
- foreach ($modules_shipping as $value) {
- if (strpos($value, '\\') !== false) {
- $class = Apps::getModuleClass($value, 'Shipping');
- $include_modules[] = ['class' => $value,
- 'file' => $class
- ];
- ];
- }
- }
- for ($i = 0, $n = \count($include_modules); $i < $n; $i++) {
- if (strpos($include_modules[$i]['class'], '\\') !== false) {
- Registry::set('Shipping_' . str_replace('\\', '_', $include_modules[$i]['class']), new $include_modules[$i]['file']);
- $module = Registry::get('Shipping_' . str_replace('\\', '_', $include_modules[$i]['class']));
- ?>
- <div class="row">
- <div class="col-md-12">
- while ($Qcols->fetch()) {
- if ($Qcols->hasValue('Collation') && !\is_null($Qcols->value('Collation'))) {
- // Skip VECTOR columns - they are binary data and cannot be converted to UTF8
- $columnType = strtolower($Qcols->value('Type'));
- if (strpos($columnType, 'vector') !== false) {
- continue;
- }
- if ($_POST['from_charset'] == 'auto') {
- $old_charset = substr($Qcols->value('Collation'), 0, strpos($Qcols->value('Collation'), '_'));
- * @param string $ip The IP address to check
- * @param string $range The CIDR range (e.g., '192.168.1.0/24')
- */
- public static function ipInRange(string $ip, string $range): bool
- {
- if (strpos($range, '/') === false) {
- return $ip === $range;
- }
- list($subnet, $bits) = explode('/', $range);
- $ip = ip2long($ip);
- // Process special vector fields
- $vector_fields = [];
- foreach ($data as $field => $value) {
- // Check if the field is meant to be a vector and starts with 'vec_'
- if (substr($field, 0, 4) === 'vec_') {
- $actual_field = substr($field, 4); // Get the actual field name without 'vec_' prefix
- $vector_fields[$actual_field] = $value; // Store the vector value
- unset($data[$field]); // Remove the special prefixed field
- }
- }
- if (!preg_match('/^[a-zA-Z0-9_]*$/', $prefix)) {
- throw new \InvalidArgumentException('Invalid table prefix');
- }
- // Ajout d'un underscore terminal si le préfixe est non vide et ne se termine pas déjà par un underscore
- if ($prefix !== '' && substr($prefix, -1) !== '_') {
- $prefix .= '_';
- }
- // Substitution sûre des tokens
- return preg_replace_callback('/:table_([a-zA-Z0-9_]+)/', function ($matches) use ($prefix) {
- if ($path === '' || $path === '.' . $separator) {
- return $systemroot;
- }
- if (substr($path, 0, 3) === '..' . $separator) {
- $path = $systemroot . $path;
- }
- // Normalize path
- $path = rtrim($path, $separator) . $separator;
- // Normalize path
- $path = rtrim($path, $separator) . $separator;
- // Absolute path
- if ($path[0] === $separator || strpos($path, $systemroot) === 0) {
- return $path;
- }
- // Relative path from 'Here'
- if (substr($path, 0, 2) === '.' . $separator || $path[0] !== '.') {
- if ($path[0] === $separator || strpos($path, $systemroot) === 0) {
- return $path;
- }
- // Relative path from 'Here'
- if (substr($path, 0, 2) === '.' . $separator || $path[0] !== '.') {
- $arrn = preg_split('/\\' . $separator . '/', $path, -1, PREG_SPLIT_NO_EMPTY);
- if ($arrn[0] !== '.') {
- array_unshift($arrn, '.');
- }
- $arrn[0] = rtrim($base, $separator);
- if ($output !== null) {
- // Envoi des Headers HTTP
- header('Content-Type: ' . $mimeType);
- // Détermine l'extension et encode si c'est du JSON
- if (strpos($mimeType, 'json') !== false) {
- // S'assurer que la sortie est un tableau/objet avant d'encoder
- if (is_array($output) || is_object($output)) {
- $output = json_encode($output, JSON_PRETTY_PRINT);
- }
- }
- // 🔧 FIX: If interpretations array is empty, use defaults based on ambiguity type
- if (empty($availableInterpretations)) {
- $ambiguityType = $ambiguityAnalysis['ambiguity_type'] ?? '';
- // For quantification queries, default to count and sum
- if (strpos($ambiguityType, 'quantification') !== false) {
- $availableInterpretations = ['count', 'sum'];
- if ($this->debug) {
- $this->logger->logSecurityEvent(
- "AmbiguityOptimizer: Empty interpretations array, using defaults for quantification: count, sum",
- // Extract type from column info (now returns array with 'type' and 'comment')
- $type = is_array($columnInfo) ? $columnInfo['type'] : $columnInfo;
- // Detect ID columns that could be foreign keys
- if (preg_match('/_id$/', $column) && strpos($type, 'int') !== false) {
- $relatedTable = str_replace('_id', '', $column);
- // Validate related table name
- $safeRelatedTable = InputValidator::sanitizeIdentifier($relatedTable);
- // Extract type from column info (now returns array with 'type' and 'comment')
- $type = is_array($columnInfo) ? $columnInfo['type'] : $columnInfo;
- // Detect ID columns that could be foreign keys
- if (preg_match('/_id$/', $column) && strpos($type, 'int') !== false) {
- $relatedTable = str_replace('_id', '', $column);
- // Validate related table name
- $safeRelatedTable = InputValidator::sanitizeIdentifier($relatedTable);
- // Load language definitions
- $CLICSHOPPING_Language = Registry::get('Language');
- DomainConfig::loadLanguageFile('rag_error_handler');
- // Suggestions based on the type of error
- if (strpos($errorMessage, 'Unknown column') !== false) {
- return CLICSHOPPING::getDef('text_column_reference_does_not_exist');
- }
- if (strpos($errorMessage, 'syntax error') !== false) {
- return CLICSHOPPING::getDef('text_sql_query_generated_error');
- // Suggestions based on the type of error
- if (strpos($errorMessage, 'Unknown column') !== false) {
- return CLICSHOPPING::getDef('text_column_reference_does_not_exist');
- }
- if (strpos($errorMessage, 'syntax error') !== false) {
- return CLICSHOPPING::getDef('text_sql_query_generated_error');
- }
- if (strpos($errorMessage, 'Table') !== false && strpos($errorMessage, 'doesn\'t exist') !== false) {
- return CLICSHOPPING::getDef('text_table_referenced_does_not_exist');
- if (strpos($errorMessage, 'syntax error') !== false) {
- return CLICSHOPPING::getDef('text_sql_query_generated_error');
- }
- if (strpos($errorMessage, 'Table') !== false && strpos($errorMessage, 'doesn\'t exist') !== false) {
- return CLICSHOPPING::getDef('text_table_referenced_does_not_exist');
- }
- // Generic suggestion
- return CLICSHOPPING::getDef('text_error_executing_query');
- if ($this->debug) {
- error_log("AmbiguousQueryDetector: LLM returned empty interpretations for ambiguous query, generating defaults");
- }
- // Generate default interpretations based on ambiguity type
- if (strpos($ambiguityType, 'quantification') !== false) {
- // For quantification queries: count vs sum
- $interpretations = [
- [
- 'type' => 'count',
- 'label' => 'Count of items',
- 'label' => 'Sum of quantities',
- 'description' => 'Sum the total quantity',
- 'sql_hint' => 'Use SUM(quantity_field)'
- ]
- ];
- } else if (strpos($ambiguityType, 'scope') !== false) {
- // For scope queries: all vs recent
- $interpretations = [
- [
- 'type' => 'all',
- 'label' => 'All items',
- $isHtmlContent = false;
- if (isset($results['text_response']) && !empty($results['text_response'])) {
- $interpretationText = $results['text_response'];
- // Check if text_response contains HTML
- $isHtmlContent = (strpos($interpretationText, '<div') !== false || strpos($interpretationText, '<p>') !== false);
- } elseif (isset($results['interpretation']) && $results['interpretation'] !== 'Array') {
- $interpretationText = $results['interpretation'];
- }
- if (!empty($interpretationText)) {
- public static function hasTemporalConnector(string $query): bool
- {
- $query = strtolower($query);
- foreach (self::$temporalConnectors as $connector) {
- if (strpos($query, $connector) !== false) {
- return true;
- }
- }
- return false;
- {
- $query = strtolower($query);
- $detected = [];
- foreach (self::$temporalConnectors as $connector) {
- if (strpos($query, $connector) !== false) {
- $detected[] = $connector;
- }
- }
- return $detected;
- public static function hasFinancialMetric(string $query): bool
- {
- $query = strtolower($query);
- foreach (self::$financialMetrics as $metric) {
- if (strpos($query, $metric) !== false) {
- return true;
- }
- }
- return false;
- public static function hasEntityKeyword(string $query): bool
- {
- $query = strtolower($query);
- foreach (SuperlativePatterns::$entityKeywords as $entity) {
- if (strpos($query, $entity) !== false) {
- return true;
- }
- }
- return false;
- {
- $query = strtolower($query);
- $detected = [];
- foreach (SuperlativePatterns::$entityKeywords as $entity) {
- if (strpos($query, $entity) !== false) {
- $detected[] = $entity;
- }
- }
- return $detected;
- */
- private static function getApiKey(): string
- {
- $api_key = CLICSHOPPING_APP_CHATGPT_CH_API_KEY;
- if (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- $api_key = CLICSHOPPING_APP_CHATGPT_CH_API_KEY_MISTRAL;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage') === 0) {
- $api_key = CLICSHOPPING_APP_CHATGPT_RA_API_KEY_VOYAGE_AI;
- }
- {
- $api_key = CLICSHOPPING_APP_CHATGPT_CH_API_KEY;
- if (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- $api_key = CLICSHOPPING_APP_CHATGPT_CH_API_KEY_MISTRAL;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage') === 0) {
- $api_key = CLICSHOPPING_APP_CHATGPT_RA_API_KEY_VOYAGE_AI;
- }
- return $api_key;
- }
- * @param string $model The embedding model to check
- * @return bool True if API keys are available, false otherwise
- */
- private static function checkApiKeys(string $model): bool
- {
- if (strpos($model, 'gpt') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY);
- } elseif (strpos($model, 'mistral') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY_MISTRAL);
- } elseif (strpos($model, 'voyage') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_RA_API_KEY_VOYAGE_AI);
- */
- private static function checkApiKeys(string $model): bool
- {
- if (strpos($model, 'gpt') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY);
- } elseif (strpos($model, 'mistral') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY_MISTRAL);
- } elseif (strpos($model, 'voyage') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_RA_API_KEY_VOYAGE_AI);
- } elseif (strpos($model, 'ollama') === 0) {
- return true;
- {
- if (strpos($model, 'gpt') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY);
- } elseif (strpos($model, 'mistral') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY_MISTRAL);
- } elseif (strpos($model, 'voyage') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_RA_API_KEY_VOYAGE_AI);
- } elseif (strpos($model, 'ollama') === 0) {
- return true;
- }
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY);
- } elseif (strpos($model, 'mistral') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_CH_API_KEY_MISTRAL);
- } elseif (strpos($model, 'voyage') === 0) {
- return !empty(CLICSHOPPING_APP_CHATGPT_RA_API_KEY_VOYAGE_AI);
- } elseif (strpos($model, 'ollama') === 0) {
- return true;
- }
- return false;
- }
- return null;
- }
- $api_key = self::getApiKey();
- if (strpos($model, 'gpt-large') === 0) {
- $config = new OpenAIConfig();
- $config->apiKey = $api_key;
- return new OpenAI3LargeEmbeddingGenerator($config);
- } elseif (strpos($model, 'gpt-medium') === 0) {
- $config = new OpenAIConfig();
- if (strpos($model, 'gpt-large') === 0) {
- $config = new OpenAIConfig();
- $config->apiKey = $api_key;
- return new OpenAI3LargeEmbeddingGenerator($config);
- } elseif (strpos($model, 'gpt-medium') === 0) {
- $config = new OpenAIConfig();
- $config->apiKey = $api_key;
- return new OpenAI3SmallEmbeddingGenerator($config);
- } elseif (strpos($model, 'mistral') === 0) {
- $config = new OpenAIConfig();
- return new OpenAI3LargeEmbeddingGenerator($config);
- } elseif (strpos($model, 'gpt-medium') === 0) {
- $config = new OpenAIConfig();
- $config->apiKey = $api_key;
- return new OpenAI3SmallEmbeddingGenerator($config);
- } elseif (strpos($model, 'mistral') === 0) {
- $config = new OpenAIConfig();
- $config->apiKey = $api_key;
- return new MistralEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3-large') === 0) {
- $config = new VoyageAIConfig();
- return new OpenAI3SmallEmbeddingGenerator($config);
- } elseif (strpos($model, 'mistral') === 0) {
- $config = new OpenAIConfig();
- $config->apiKey = $api_key;
- return new MistralEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3-large') === 0) {
- $config = new VoyageAIConfig();
- $config->apiKey = $api_key;
- return new Voyage3LargeEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3-lite') === 0) {
- $config = new VoyageAIConfig();
- return new MistralEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3-large') === 0) {
- $config = new VoyageAIConfig();
- $config->apiKey = $api_key;
- return new Voyage3LargeEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3-lite') === 0) {
- $config = new VoyageAIConfig();
- $config->apiKey = $api_key;
- return new Voyage3LiteEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3') === 0) {
- $config = new VoyageAIConfig();
- return new Voyage3LargeEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3-lite') === 0) {
- $config = new VoyageAIConfig();
- $config->apiKey = $api_key;
- return new Voyage3LiteEmbeddingGenerator($config);
- } elseif (strpos($model, 'voyage3') === 0) {
- $config = new VoyageAIConfig();
- $config->apiKey = $api_key;
- return new Voyage3EmbeddingGenerator($config);
- } else {
- return new OllamaEmbeddingGenerator($model);
- $errorMessage .= " (estimated tokens: {$estimatedTokens}, chunk size: {$token_length})";
- }
- error_log($errorMessage);
- if (strpos($e->getMessage(), 'maximum context length') !== false && $token_length > 200) {
- error_log("Retrying with smaller chunk size...");
- return self::createEmbedding($path_file_upload, $text_description, (int)($token_length / 2));
- }
- return null;
- */
- private static function estimateTokenCount(string $text): int
- {
- $model = CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL;
- if (strpos($model, 'gpt') === 0 || strpos($model, 'voyage') === 0) {
- $avgCharsPerToken = 3.5;
- return (int)ceil(strlen($text) / $avgCharsPerToken);
- }
- return (int)ceil(strlen($text) / 4);
- *
- * @return int The embedding length in dimensions for the selected model
- */
- public static function getEmbeddingLength(): int
- {
- if (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-large') === 0) {
- return 3072;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-medium') === 0) {
- return 1536;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- return 1024;
- */
- public static function getEmbeddingLength(): int
- {
- if (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-large') === 0) {
- return 3072;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-medium') === 0) {
- return 1536;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- return 1024;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-large') === 0) {
- return 4096;
- {
- if (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-large') === 0) {
- return 3072;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-medium') === 0) {
- return 1536;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- return 1024;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-large') === 0) {
- return 4096;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-lite') === 0) {
- return 384;
- return 3072;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'gpt-medium') === 0) {
- return 1536;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- return 1024;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-large') === 0) {
- return 4096;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-lite') === 0) {
- return 384;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3') === 0) {
- return 1024;
- return 1536;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'mistral') === 0) {
- return 1024;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-large') === 0) {
- return 4096;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-lite') === 0) {
- return 384;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3') === 0) {
- return 1024;
- } else {
- return 1536;
- return 1024;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-large') === 0) {
- return 4096;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3-lite') === 0) {
- return 384;
- } elseif (strpos(CLICSHOPPING_APP_CHATGPT_RA_EMBEDDING_MODEL, 'voyage3') === 0) {
- return 1024;
- } else {
- return 1536;
- }
- }
- 'voyage3-lite' => 4000,
- 'nomic-embed-text' => 8192,
- ];
- foreach ($contextLengths as $modelPrefix => $length) {
- if (strpos($model, $modelPrefix) === 0) {
- return $length;
- }
- }
- return 4096;
- 'voyage3-lite' => 300,
- 'nomic-embed-text' => 800,
- ];
- foreach ($chunkSizes as $modelPrefix => $size) {
- if (strpos($model, $modelPrefix) === 0) {
- return $size;
- }
- }
- return 500;
- * @param string $model
- * @return string
- */
- private static function getModelProvider(string $model): string
- {
- if (strpos($model, 'gpt') === 0) return 'openai';
- if (strpos($model, 'mistral') === 0) return 'mistral';
- if (strpos($model, 'voyage') === 0) return 'voyageai';
- if (strpos($model, 'nomic') === 0) return 'ollama';
- return 'unknown';
- * @return string
- */
- private static function getModelProvider(string $model): string
- {
- if (strpos($model, 'gpt') === 0) return 'openai';
- if (strpos($model, 'mistral') === 0) return 'mistral';
- if (strpos($model, 'voyage') === 0) return 'voyageai';
- if (strpos($model, 'nomic') === 0) return 'ollama';
- return 'unknown';
- }
- */
- private static function getModelProvider(string $model): string
- {
- if (strpos($model, 'gpt') === 0) return 'openai';
- if (strpos($model, 'mistral') === 0) return 'mistral';
- if (strpos($model, 'voyage') === 0) return 'voyageai';
- if (strpos($model, 'nomic') === 0) return 'ollama';
- return 'unknown';
- }
- private static function getModelProvider(string $model): string
- {
- if (strpos($model, 'gpt') === 0) return 'openai';
- if (strpos($model, 'mistral') === 0) return 'mistral';
- if (strpos($model, 'voyage') === 0) return 'voyageai';
- if (strpos($model, 'nomic') === 0) return 'ollama';
- return 'unknown';
- }
- //*********************
- if ($value === null) {
- return null;
- }
- // Si la valeur est déjà une chaîne formatée correctement, la retourner telle quelle
- if (is_string($value) && strpos($value, '[') === 0) {
- return $value;
- }
- // Convertir le tableau en chaîne formatée pour MariaDB
- if (is_array($value)) {
- if (isset($specialCases[$entityType])) {
- return $specialCases[$entityType];
- }
- // Handle compound words with underscores (e.g., "return_orders" -> "return_order")
- if (strpos($entityType, '_') !== false) {
- $parts = explode('_', $entityType);
- $lastPart = array_pop($parts);
- // Apply singularization to the last part only
- $singularLastPart = self::singularizeWord($lastPart);
- if (strlen($word) < 2) {
- return $word;
- }
- // Words ending in "ies" -> "y" (e.g., "categories" -> "category")
- if (substr($word, -3) === 'ies') {
- return substr($word, 0, -3) . 'y';
- }
- // Words ending in "es" -> remove "es" (e.g., "boxes" -> "box")
- if (substr($word, -2) === 'es') {
- if (substr($word, -3) === 'ies') {
- return substr($word, 0, -3) . 'y';
- }
- // Words ending in "es" -> remove "es" (e.g., "boxes" -> "box")
- if (substr($word, -2) === 'es') {
- return substr($word, 0, -2);
- }
- // Words ending in "s" -> remove "s" (e.g., "products" -> "product")
- if (substr($word, -1) === 's') {
- if (substr($word, -2) === 'es') {
- return substr($word, 0, -2);
- }
- // Words ending in "s" -> remove "s" (e.g., "products" -> "product")
- if (substr($word, -1) === 's') {
- return substr($word, 0, -1);
- }
- // No change needed
- return $word;
- if (isset($specialCases[$entityType])) {
- return $specialCases[$entityType];
- }
- // Handle compound words with underscores
- if (strpos($entityType, '_') !== false) {
- $parts = explode('_', $entityType);
- $lastPart = array_pop($parts);
- // Apply pluralization to the last part only
- $pluralLastPart = self::pluralizeWord($lastPart);
- if (strlen($word) < 2) {
- return $word;
- }
- // Words ending in "y" -> "ies" (e.g., "category" -> "categories")
- if (substr($word, -1) === 'y') {
- return substr($word, 0, -1) . 'ies';
- }
- // Words ending in "s", "x", "z", "ch", "sh" -> add "es"
- if (preg_match('/(s|x|z|ch|sh)$/i', $word)) {
- // Check for table names in FROM clause
- foreach ($entityColumnMap as $columnName => $entityType) {
- $tableName = str_replace('_id', '', $columnName);
- // Check if table name appears in query
- if (strpos($sqlLower, "from {$tableName}") !== false ||
- strpos($sqlLower, "from clic_{$tableName}") !== false ||
- strpos($sqlLower, "join {$tableName}") !== false ||
- strpos($sqlLower, "join clic_{$tableName}") !== false) {
- return [
- foreach ($entityColumnMap as $columnName => $entityType) {
- $tableName = str_replace('_id', '', $columnName);
- // Check if table name appears in query
- if (strpos($sqlLower, "from {$tableName}") !== false ||
- strpos($sqlLower, "from clic_{$tableName}") !== false ||
- strpos($sqlLower, "join {$tableName}") !== false ||
- strpos($sqlLower, "join clic_{$tableName}") !== false) {
- return [
- 'entity_id' => null, // Can't extract ID from query alone
- $tableName = str_replace('_id', '', $columnName);
- // Check if table name appears in query
- if (strpos($sqlLower, "from {$tableName}") !== false ||
- strpos($sqlLower, "from clic_{$tableName}") !== false ||
- strpos($sqlLower, "join {$tableName}") !== false ||
- strpos($sqlLower, "join clic_{$tableName}") !== false) {
- return [
- 'entity_id' => null, // Can't extract ID from query alone
- 'entity_type' => $entityType,
- // Check if table name appears in query
- if (strpos($sqlLower, "from {$tableName}") !== false ||
- strpos($sqlLower, "from clic_{$tableName}") !== false ||
- strpos($sqlLower, "join {$tableName}") !== false ||
- strpos($sqlLower, "join clic_{$tableName}") !== false) {
- return [
- 'entity_id' => null, // Can't extract ID from query alone
- 'entity_type' => $entityType,
- ];
- {
- $markers = self::getResetMarkers();
- $queryLower = mb_strtolower($query);
- foreach ($markers as $marker) {
- if (strpos($queryLower, $marker) !== false) {
- return true;
- }
- }
- return false;
- $markers = self::getResetMarkers();
- $queryLower = mb_strtolower($query);
- $foundMarkers = [];
- foreach ($markers as $marker) {
- if (strpos($queryLower, $marker) !== false) {
- $foundMarkers[] = $marker;
- }
- }
- $hasReset = !empty($foundMarkers);
- {
- $keywords = self::getModificationKeywords();
- $queryLower = mb_strtolower($query);
- foreach ($keywords as $keyword) {
- if (strpos($queryLower, $keyword) !== false) {
- return true;
- }
- }
- return false;
- {
- $keywords = self::getModificationKeywords();
- $queryLower = mb_strtolower($query);
- foreach ($keywords as $keyword) {
- if (strpos($queryLower, $keyword) !== false) {
- return $keyword;
- }
- }
- return null;
- $isHtmlContent = false;
- if (isset($results['text_response']) && !empty($results['text_response'])) {
- $interpretationText = $results['text_response'];
- // Check if text_response contains HTML
- $isHtmlContent = (strpos($interpretationText, '<div') !== false || strpos($interpretationText, '<p>') !== false);
- } elseif (isset($results['response']) && !empty($results['response'])) {
- $interpretationText = $results['response'];
- } elseif (isset($results['interpretation']) && $results['interpretation'] !== 'Array') {
- $interpretationText = $results['interpretation'];
- }
- foreach ($termGroups as $groupType => $terms) {
- $weight = $this->termWeights[$groupType] ?? 0.5;
- foreach ($terms as $term) {
- if (strpos($query, $term) !== false) {
- $domainScore += $weight;
- $matchedTerms[] = [
- 'term' => $term,
- 'type' => $groupType,
- 'weight' => $weight,
- $supplierBonus = 0;
- $manufacturerBonus = 0;
- foreach ($supplierIndicators as $indicator) {
- if (strpos($query, $indicator) !== false) {
- $supplierBonus += 1.0;
- }
- }
- foreach ($manufacturerIndicators as $indicator) {
- $supplierBonus += 1.0;
- }
- }
- foreach ($manufacturerIndicators as $indicator) {
- if (strpos($query, $indicator) !== false) {
- $manufacturerBonus += 1.0;
- }
- }
- $scores['suppliers']['score'] += $supplierBonus;
- if (abs($reviewScore - $sentimentScore) < 0.5) {
- $sentimentIndicators = ['sentiment', 'feeling', 'positive', 'negative', 'emotion', 'analysis'];
- $sentimentBonus = 0;
- foreach ($sentimentIndicators as $indicator) {
- if (strpos($query, $indicator) !== false) {
- $sentimentBonus += 0.5;
- }
- }
- if ($sentimentBonus > 0) {
- 'wrong category',
- 'incorrect classification'
- ];
- foreach ($classificationKeywords as $keyword) {
- if (strpos($comment, $keyword) !== false) {
- return true;
- }
- }
- if ($reason === 'irrelevant') {
- $isClassificationError = false;
- $errorType = 'unknown';
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- $isClassificationError = false;
- $errorType = 'unknown';
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $errorType = 'unknown';
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- $errorType = 'irrelevant_result';
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- $errorType = 'irrelevant_result';
- } elseif ($reason === 'incomplete' && strpos($comment, 'wrong') !== false) {
- $isClassificationError = true;
- $errorType = 'partial_misclassification';
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- $errorType = 'irrelevant_result';
- } elseif ($reason === 'incomplete' && strpos($comment, 'wrong') !== false) {
- $isClassificationError = true;
- $errorType = 'partial_misclassification';
- }
- if ($isClassificationError) {
- $isClassificationError = false;
- $errorType = 'unknown';
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- $isClassificationError = false;
- $errorType = 'unknown';
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $errorType = 'unknown';
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- // Detect classification errors
- if (strpos($comment, 'wrong type') !== false ||
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- $errorType = 'irrelevant_result';
- strpos($comment, 'misclassified') !== false ||
- strpos($comment, 'should be analytics') !== false ||
- strpos($comment, 'should be semantic') !== false) {
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- $errorType = 'irrelevant_result';
- } elseif ($reason === 'incomplete' && strpos($comment, 'wrong') !== false) {
- $isClassificationError = true;
- $errorType = 'partial_misclassification';
- $isClassificationError = true;
- $errorType = 'misclassification';
- } elseif ($reason === 'irrelevant' || strpos($comment, 'irrelevant') !== false) {
- $isClassificationError = true;
- $errorType = 'irrelevant_result';
- } elseif ($reason === 'incomplete' && strpos($comment, 'wrong') !== false) {
- $isClassificationError = true;
- $errorType = 'partial_misclassification';
- }
- if ($isClassificationError) {
- if (preg_match('/is:\s*["\'](.+?)["\']$/i', $cleaned, $matches)) {
- $cleaned = $matches[1];
- }
- // STEP 4: Remove leading/trailing quotes if they wrap the entire string
- if ((substr($cleaned, 0, 1) === '"' && substr($cleaned, -1) === '"') ||
- (substr($cleaned, 0, 1) === "'" && substr($cleaned, -1) === "'")) {
- $cleaned = substr($cleaned, 1, -1);
- }
- return trim($cleaned);
- if (preg_match('/is:\s*["\'](.+?)["\']$/i', $cleaned, $matches)) {
- $cleaned = $matches[1];
- }
- // STEP 4: Remove leading/trailing quotes if they wrap the entire string
- if ((substr($cleaned, 0, 1) === '"' && substr($cleaned, -1) === '"') ||
- (substr($cleaned, 0, 1) === "'" && substr($cleaned, -1) === "'")) {
- $cleaned = substr($cleaned, 1, -1);
- }
- return trim($cleaned);
- $cleaned = $matches[1];
- }
- // STEP 4: Remove leading/trailing quotes if they wrap the entire string
- if ((substr($cleaned, 0, 1) === '"' && substr($cleaned, -1) === '"') ||
- (substr($cleaned, 0, 1) === "'" && substr($cleaned, -1) === "'")) {
- $cleaned = substr($cleaned, 1, -1);
- }
- return trim($cleaned);
- }
- $cleaned = $matches[1];
- }
- // STEP 4: Remove leading/trailing quotes if they wrap the entire string
- if ((substr($cleaned, 0, 1) === '"' && substr($cleaned, -1) === '"') ||
- (substr($cleaned, 0, 1) === "'" && substr($cleaned, -1) === "'")) {
- $cleaned = substr($cleaned, 1, -1);
- }
- return trim($cleaned);
- }
- // Check if query has entity keywords (database query, not web search)
- // 🔧 MIGRATION: Use centralized EntityKeywordsPattern instead of WebSearchPatterns
- $hasEntityKeyword = false;
- foreach (WebSearchPatterns::getEntityKeywords() as $entity) {
- if (strpos($query, $entity) !== false) {
- $hasEntityKeyword = true;
- break;
- }
- }
- }
- // Check if query has financial metric keywords (analytics query, not web search)
- $hasFinancialKeyword = false;
- foreach ($financialMetricKeywords as $keyword) {
- if (strpos($query, $keyword) !== false) {
- $hasFinancialKeyword = true;
- break;
- }
- }
- }
- // Only apply trends/news override if NO entity keywords AND NO financial keywords present
- if (!$hasEntityKeyword && !$hasFinancialKeyword) {
- foreach (WebSearchPatterns::$trendsNewsKeywords as $keyword) {
- if (strpos($query, $keyword) !== false) {
- $analysis['intent_type'] = 'web_search';
- $analysis['confidence'] = 0.95;
- $analysis['override_reason'] = "Trends/news keyword detected: $keyword (no entity/financial keywords)";
- $analysis['detection_method'] = 'pattern_post_filter';
- return $analysis;
- // ========================================================================
- // STEP 2: Check for competitor keywords (ENGLISH ONLY)
- // ========================================================================
- foreach (WebSearchPatterns::$competitorKeywords as $keyword) {
- if (strpos($query, $keyword) !== false) {
- $analysis['intent_type'] = 'web_search';
- $analysis['confidence'] = 0.95;
- $analysis['override_reason'] = "Competitor keyword detected: $keyword";
- $analysis['detection_method'] = 'pattern_post_filter';
- return $analysis;
- $externalSites[] = strtolower($row['site_domain']);
- }
- // Check if query mentions any configured external site
- foreach ($externalSites as $site) {
- if (strpos($query, $site) !== false) {
- $analysis['intent_type'] = 'web_search';
- $analysis['confidence'] = 0.95;
- $analysis['override_reason'] = "External site detected: $site (from database)";
- $analysis['detection_method'] = 'pattern_post_filter';
- return $analysis;
- // Only check comparison if query is price-related
- $hasPriceKeyword = false;
- foreach (WebSearchPatterns::$priceKeywords as $priceWord) {
- if (strpos($query, $priceWord) !== false) {
- $hasPriceKeyword = true;
- break;
- }
- }
- }
- }
- if ($hasPriceKeyword) {
- foreach (WebSearchPatterns::$comparisonKeywords as $keyword) {
- if (strpos($query, $keyword) !== false) {
- // Additional check: ensure it's not just internal comparison
- // If query contains "database" or "internal", it's likely hybrid, not pure web_search
- if (strpos($query, 'database') === false && strpos($query, 'internal') === false) {
- $analysis['intent_type'] = 'web_search';
- $analysis['confidence'] = 0.90;
- if ($hasPriceKeyword) {
- foreach (WebSearchPatterns::$comparisonKeywords as $keyword) {
- if (strpos($query, $keyword) !== false) {
- // Additional check: ensure it's not just internal comparison
- // If query contains "database" or "internal", it's likely hybrid, not pure web_search
- if (strpos($query, 'database') === false && strpos($query, 'internal') === false) {
- $analysis['intent_type'] = 'web_search';
- $analysis['confidence'] = 0.90;
- $analysis['override_reason'] = "Price comparison detected: $keyword";
- $analysis['detection_method'] = 'pattern_post_filter';
- return $analysis;
- // Clear from Memcached (note: Memcached doesn't support key pattern matching easily)
- // We'll rely on TTL expiration for Memcached
- // Clear from file cache
- foreach ($this->promptCache as $key => $data) {
- if (strpos($key, $prefix) === 0) {
- unset($this->promptCache[$key]);
- $cleared++;
- }
- }
- // iterate through all keys. We'll rely on TTL expiration for Memcached.
- // For production use, consider using Redis for better invalidation support.
- // Invalidate from file cache
- foreach ($this->promptCache as $key => $data) {
- if (strpos($key, self::CACHE_TYPE_SQL) === 0) {
- if (isset($data['tables_used']) && in_array($cleanTableName, $data['tables_used'], true)) {
- unset($this->promptCache[$key]);
- $invalidated++;
- }
- }
- }
- }
- // Invalidate from file cache
- foreach ($this->promptCache as $key => $data) {
- if (strpos($key, self::CACHE_TYPE_SQL) === 0) {
- if (isset($data['tables_used'])) {
- $intersection = array_intersect($cleanTableNames, $data['tables_used']);
- if (!empty($intersection)) {
- unset($this->promptCache[$key]);
- $invalidated++;
- {
- // Remove backticks and quotes
- $tableName = str_replace(['`', '"', "'"], '', $tableName);
- // Remove database prefix (e.g., database.table -> table)
- if (strpos($tableName, '.') !== false) {
- $parts = explode('.', $tableName);
- $tableName = end($parts);
- }
- // Remove alias (take only the first word)
- return self::PRICING[$model];
- }
- // Match partiel (ex: "gpt-4-0613" match "gpt-4")
- foreach (self::PRICING as $knownModel => $pricing) {
- if (strpos($model, $knownModel) !== false) {
- return $pricing;
- }
- }
- // Détection par provider
- return $pricing;
- }
- }
- // Détection par provider
- if (strpos($model, 'gpt') !== false) {
- return self::PRICING['gpt-3.5-turbo']; // Défaut OpenAI
- }
- if (strpos($model, 'claude') !== false) {
- return self::PRICING['claude-3-haiku']; // Défaut Anthropic (le moins cher)
- }
- // Détection par provider
- if (strpos($model, 'gpt') !== false) {
- return self::PRICING['gpt-3.5-turbo']; // Défaut OpenAI
- }
- if (strpos($model, 'claude') !== false) {
- return self::PRICING['claude-3-haiku']; // Défaut Anthropic (le moins cher)
- }
- if (strpos($model, 'mistral') !== false) {
- return self::PRICING['mistral-small']; // Défaut Mistral
- }
- return self::PRICING['gpt-3.5-turbo']; // Défaut OpenAI
- }
- if (strpos($model, 'claude') !== false) {
- return self::PRICING['claude-3-haiku']; // Défaut Anthropic (le moins cher)
- }
- if (strpos($model, 'mistral') !== false) {
- return self::PRICING['mistral-small']; // Défaut Mistral
- }
- if (strpos($model, 'llama') !== false || strpos($model, 'ollama') !== false) {
- return [0.0, 0.0]; // Local, gratuit
- }
- return self::PRICING['claude-3-haiku']; // Défaut Anthropic (le moins cher)
- }
- if (strpos($model, 'mistral') !== false) {
- return self::PRICING['mistral-small']; // Défaut Mistral
- }
- if (strpos($model, 'llama') !== false || strpos($model, 'ollama') !== false) {
- return [0.0, 0.0]; // Local, gratuit
- }
- return null;
- }
- $metrics = array_merge($metrics, $componentStats);
- }
- // Méthodes spécifiques par type de composant
- switch (true) {
- case strpos($name, 'Planner') !== false:
- $metrics['type'] = 'planner';
- $metrics['total_plans'] = $componentStats['total_plans_created'] ?? 0;
- $metrics['avg_steps'] = $componentStats['avg_steps_per_plan'] ?? 0;
- break;
- $metrics['type'] = 'planner';
- $metrics['total_plans'] = $componentStats['total_plans_created'] ?? 0;
- $metrics['avg_steps'] = $componentStats['avg_steps_per_plan'] ?? 0;
- break;
- case strpos($name, 'Memory') !== false:
- $metrics['type'] = 'memory';
- if (method_exists($component, 'getStats')) {
- $memStats = $component->getStats();
- $metrics['total_interactions'] = $memStats['total_interactions'] ?? 0;
- $metrics['memory_size'] = $memStats['total_size'] ?? 0;
- $metrics['total_interactions'] = $memStats['total_interactions'] ?? 0;
- $metrics['memory_size'] = $memStats['total_size'] ?? 0;
- }
- break;
- case strpos($name, 'Correction') !== false:
- $metrics['type'] = 'correction';
- if (method_exists($component, 'getLearningStats')) {
- $learnStats = $component->getLearningStats();
- $metrics['correction_accuracy'] = $learnStats['correction_accuracy'] ?? 0;
- $metrics['learned_patterns'] = $learnStats['learned_patterns'] ?? 0;
- $metrics['correction_accuracy'] = $learnStats['correction_accuracy'] ?? 0;
- $metrics['learned_patterns'] = $learnStats['learned_patterns'] ?? 0;
- }
- break;
- case strpos($name, 'WebSearch') !== false:
- $metrics['type'] = 'web_search';
- $metrics['cache_hit_rate'] = $this->extractCacheHitRate($componentStats);
- break;
- }
- if ($serverVersion) {
- $serverVersionLower = strtolower($serverVersion);
- // Extraire et formater correctement la version
- if (strpos($serverVersionLower, 'mariadb') !== false) {
- // Format typique: "10.11.8-MariaDB" ou "11.7.0-mariadb"
- preg_match('/(\d+\.\d+\.\d+)/', $serverVersion, $matches);
- if (!empty($matches[1])) {
- $versionNumber = $matches[1];
- return true;
- }
- // Fuzzy match
- foreach ($allFields as $field) {
- if (strpos($field, $word) !== false || strpos($word, $field) !== false) {
- return true;
- }
- }
- // Check against non-database words
- if (in_array($fieldName, $skipFields, true)) {
- return null;
- }
- // Remove _id suffix for non-ID fields
- if ($fieldName !== 'id' && preg_match('/_id$/', $fieldName)) {
- return null;
- }
- return $fieldName;
- }
- if (self::$prefixDb === null) {
- self::$prefixDb = CLICSHOPPING::getConfig('db_table_prefix');
- }
- // Add prefix if not already present
- if (strpos($tableName, self::$prefixDb) !== 0) {
- $tableName = self::$prefixDb . $tableName;
- }
- $connection = self::getEntityManager()->getConnection();
- $affectedRows = $connection->insert($tableName, $data);
- if (self::$prefixDb === null) {
- self::$prefixDb = CLICSHOPPING::getConfig('db_table_prefix');
- }
- // Add prefix if not already present
- if (strpos($tableName, self::$prefixDb) !== 0) {
- $tableName = self::$prefixDb . $tableName;
- }
- $connection = self::getEntityManager()->getConnection();
- return $connection->update($tableName, $data, $criteria);
- if (self::$prefixDb === null) {
- self::$prefixDb = CLICSHOPPING::getConfig('db_table_prefix');
- }
- // Add prefix if not already present
- if (strpos($tableName, self::$prefixDb) !== 0) {
- $tableName = self::$prefixDb . $tableName;
- }
- $connection = self::getEntityManager()->getConnection();
- return $connection->delete($tableName, $criteria);
- error_log("text_order_calculation length: " . strlen($orderCalculation) . " chars");
- error_log("text_query_examples length: " . strlen($queryExamples) . " chars");
- error_log("sqlFormatInstructions length: " . strlen($sqlFormatInstructions) . " chars");
- error_log("text_response_format length: " . strlen($responseFormat) . " chars");
- error_log("text_multi_token_rules length: " . strlen($multiTokenRules) . " chars");
- error_log("Contains 'MULTI-TOKEN' in multiTokenRules: " . (strpos($multiTokenRules, 'MULTI-TOKEN') !== false ? 'YES' : 'NO'));
- error_log("Contains 'ABSOLUTE RULE' in aggregationRules: " . (strpos($aggregationRules, 'ABSOLUTE RULE') !== false ? 'YES' : 'NO'));
- error_log("First 200 chars of multiTokenRules: " . substr($multiTokenRules, 0, 200));
- error_log("================================================================================");
- }
- error_log("text_query_examples length: " . strlen($queryExamples) . " chars");
- error_log("sqlFormatInstructions length: " . strlen($sqlFormatInstructions) . " chars");
- error_log("text_response_format length: " . strlen($responseFormat) . " chars");
- error_log("text_multi_token_rules length: " . strlen($multiTokenRules) . " chars");
- error_log("Contains 'MULTI-TOKEN' in multiTokenRules: " . (strpos($multiTokenRules, 'MULTI-TOKEN') !== false ? 'YES' : 'NO'));
- error_log("Contains 'ABSOLUTE RULE' in aggregationRules: " . (strpos($aggregationRules, 'ABSOLUTE RULE') !== false ? 'YES' : 'NO'));
- error_log("First 200 chars of multiTokenRules: " . substr($multiTokenRules, 0, 200));
- error_log("================================================================================");
- }
- // Construct complete message in the correct order
- error_log("================================================================================");
- error_log("DEBUG PromptBuilder::buildSystemMessage() - FINAL");
- error_log("================================================================================");
- error_log("Language ID: " . $this->languageId);
- error_log("Final message length: " . strlen($finalMessage));
- error_log("Contains 'CRITICAL RULES': " . (strpos($finalMessage, 'CRITICAL RULES') !== false ? 'YES' : 'NO'));
- error_log("Contains 'products_quantity': " . (strpos($finalMessage, 'products_quantity') !== false ? 'YES' : 'NO'));
- error_log("First 500 chars: " . substr($finalMessage, 0, 500));
- error_log("================================================================================");
- }
- error_log("DEBUG PromptBuilder::buildSystemMessage() - FINAL");
- error_log("================================================================================");
- error_log("Language ID: " . $this->languageId);
- error_log("Final message length: " . strlen($finalMessage));
- error_log("Contains 'CRITICAL RULES': " . (strpos($finalMessage, 'CRITICAL RULES') !== false ? 'YES' : 'NO'));
- error_log("Contains 'products_quantity': " . (strpos($finalMessage, 'products_quantity') !== false ? 'YES' : 'NO'));
- error_log("First 500 chars: " . substr($finalMessage, 0, 500));
- error_log("================================================================================");
- }
- return $finalMessage;
- while ($tableRow = $tablesResult->fetch()) {
- $tableName = array_values($tableRow)[0];
- // Skip non-clic tables
- if (strpos($tableName, 'clic_') !== 0) {
- continue;
- }
- $schema .= "Table: {$tableName}\n";
- }
- }
- foreach ($tablesList as $tableName) {
- // Skip technical tables
- if (strpos($tableName, '_embedding') !== false || strpos($tableName, $prefix . 'rag_') === 0) {
- continue;
- }
- $this->totalTables++;
- }
- }
- foreach ($tablesList as $tableName) {
- // Skip technical tables
- if (strpos($tableName, '_embedding') !== false || strpos($tableName, $prefix . 'rag_') === 0) {
- continue;
- }
- $this->totalTables++;
- while ($Qembeddings->fetch()) {
- $tableName = $Qembeddings->value('table_name');
- // Skip technical tables (should not be in embeddings, but filter just in case)
- if (strpos($tableName, '_embedding') !== false || strpos($tableName, 'clic_rag_') === 0) {
- continue;
- }
- $embeddingText = $Qembeddings->value('embedding_text');
- while ($Qembeddings->fetch()) {
- $tableName = $Qembeddings->value('table_name');
- // Skip technical tables (should not be in embeddings, but filter just in case)
- if (strpos($tableName, '_embedding') !== false || strpos($tableName, 'clic_rag_') === 0) {
- continue;
- }
- $embeddingText = $Qembeddings->value('embedding_text');
- * @param string $tableName Table name
- * @return bool True if junction table
- */
- private function isJunctionTable(string $tableName): bool
- {
- return preg_match('/_to_/', $tableName) === 1;
- }
- /**
- * Calculate cosine similarity between two vectors
- *
- // Check if the path is within allowed directories
- $isAllowed = false;
- foreach ($allowedDirs as $allowedDir) {
- $normalizedAllowedDir = str_replace('\\', '/', realpath($allowedDir));
- if ($normalizedAllowedDir && strpos($realPath, $normalizedAllowedDir) === 0) {
- $isAllowed = true;
- break;
- }
- }
- * @return bool True if the text contains valid JSON, false otherwise.
- */
- private static function validateJsonStructure(string $text): bool
- {
- // Si le texte contient du JSON, vérifier sa validité
- if (strpos($text, '{') !== false || strpos($text, '[') !== false) {
- return json_last_error() === JSON_ERROR_NONE;
- }
- return true; // Pas de JSON détecté
- }
- */
- private static function containsMaliciousPatterns(string $text): bool
- {
- $lowerText = strtolower($text);
- foreach (ObfuscationPatterns::$maliciousKeywords as $keyword) {
- if (strpos($lowerText, $keyword) !== false) {
- return true;
- }
- }
- return false;
- */
- private function detectQueryType(string $sql): string
- {
- $sql = trim(strtoupper($sql));
- if (strpos($sql, 'SELECT') === 0) return 'SELECT';
- if (strpos($sql, 'INSERT') === 0) return 'INSERT';
- if (strpos($sql, 'UPDATE') === 0) return 'UPDATE';
- if (strpos($sql, 'DELETE') === 0) return 'DELETE';
- return 'UNKNOWN';
- private function detectQueryType(string $sql): string
- {
- $sql = trim(strtoupper($sql));
- if (strpos($sql, 'SELECT') === 0) return 'SELECT';
- if (strpos($sql, 'INSERT') === 0) return 'INSERT';
- if (strpos($sql, 'UPDATE') === 0) return 'UPDATE';
- if (strpos($sql, 'DELETE') === 0) return 'DELETE';
- return 'UNKNOWN';
- }
- {
- $sql = trim(strtoupper($sql));
- if (strpos($sql, 'SELECT') === 0) return 'SELECT';
- if (strpos($sql, 'INSERT') === 0) return 'INSERT';
- if (strpos($sql, 'UPDATE') === 0) return 'UPDATE';
- if (strpos($sql, 'DELETE') === 0) return 'DELETE';
- return 'UNKNOWN';
- }
- $sql = trim(strtoupper($sql));
- if (strpos($sql, 'SELECT') === 0) return 'SELECT';
- if (strpos($sql, 'INSERT') === 0) return 'INSERT';
- if (strpos($sql, 'UPDATE') === 0) return 'UPDATE';
- if (strpos($sql, 'DELETE') === 0) return 'DELETE';
- return 'UNKNOWN';
- }
- /**
- public static function hasTimePeriod(string $query): bool
- {
- $query = strtolower($query);
- foreach (self::$timePeriods as $period) {
- if (strpos($query, $period) !== false) {
- return true;
- }
- }
- return false;
- {
- $query = strtolower($query);
- $detected = [];
- foreach (self::$financialMetrics as $metric) {
- if (strpos($query, $metric) !== false) {
- $detected[] = $metric;
- }
- }
- return $detected;
- {
- $query = strtolower($query);
- $detected = [];
- foreach (self::$timePeriods as $period) {
- if (strpos($query, $period) !== false) {
- $detected[] = $period;
- }
- }
- return $detected;
- $hasConjunction = false;
- $conjunctionUsed = '';
- foreach ($conjunctions as $conj) {
- if (strpos($query, $conj) !== false) {
- $hasConjunction = true;
- $conjunctionUsed = trim($conj);
- break;
- }
- }
- $part = trim($part);
- $partIntent = null;
- // Check analytics
- foreach ($analyticsKeywords as $keyword) {
- if (strpos($part, $keyword) !== false) {
- $partIntent = 'analytics';
- break;
- }
- }
- }
- // Check semantic
- if ($partIntent === null) {
- foreach ($semanticKeywords as $keyword) {
- if (strpos($part, $keyword) !== false) {
- $partIntent = 'semantic';
- break;
- }
- }
- }
- }
- // Check web_search
- if ($partIntent === null) {
- foreach ($webSearchKeywords as $keyword) {
- if (strpos($part, $keyword) !== false) {
- $partIntent = 'web_search';
- break;
- }
- }
- }
- // Simple routing
- // --------------------------------------------------------------------------------
- // POST /agentic_commerce/delegate_payment - Handle delegated payment vaulting
- // --------------------------------------------------------------------------------
- if ($method === 'POST' && ($hasDelegatePaymentParam || strpos($path, '/agentic_commerce/delegate_payment') !== false)) {
- $headers = [
- 'idempotency_key' => $_SERVER['HTTP_IDEMPOTENCY_KEY'] ?? null,
- 'request_id' => $_SERVER['HTTP_REQUEST_ID'] ?? null
- ];
- $result = $CLICSHOPPING_getRetailers->handleDelegatePayment($input, $headers);
- // --------------------------------------------------------------------------------
- // GET /products - Returns product catalog
- // --------------------------------------------------------------------------------
- if ($method === 'GET' && ($hasProductsParam || strpos($path, '/products') !== false)) {
- // Return full product catalog
- $products = $CLICSHOPPING_getRetailers->getProducts();
- echo json_encode(['products' => $products], JSON_UNESCAPED_SLASHES);
- exit;
- } elseif (!empty($checkoutIdParam)) {
- // Fallback ou prise en compte du paramètre 'id' si l'ID n'est pas dans le chemin
- $sessionId = $checkoutIdParam;
- }
- if ($method === 'POST' && ($hasCheckoutParam || strpos($path, '/checkout_sessions') !== false)) {
- if ($sessionId) {
- if ($hasCompleteParam || strpos($path, '/complete') !== false) {
- $validation = $CLICSHOPPING_getRetailers->validateAcpInput($input, 'complete', $input['items'] ?? []);
- if (!empty($validation)) {
- http_response_code(400);
- $sessionId = $checkoutIdParam;
- }
- if ($method === 'POST' && ($hasCheckoutParam || strpos($path, '/checkout_sessions') !== false)) {
- if ($sessionId) {
- if ($hasCompleteParam || strpos($path, '/complete') !== false) {
- $validation = $CLICSHOPPING_getRetailers->validateAcpInput($input, 'complete', $input['items'] ?? []);
- if (!empty($validation)) {
- http_response_code(400);
- echo json_encode(['messages' => $validation], JSON_UNESCAPED_SLASHES);
- exit;
- echo json_encode($result['checkout_session'], JSON_UNESCAPED_SLASHES);
- } else {
- echo json_encode($result, JSON_UNESCAPED_SLASHES);
- }
- }
- } elseif ($hasCancelParam || strpos($path, '/cancel') !== false) {
- $result = $CLICSHOPPING_getRetailers->cancelSession($sessionId);
- if ($result === null) {
- http_response_code(404);
- echo json_encode(['error' => 'Session not found']);
- } else {
- exit;
- }
- // --------------------------------------------------------------------------------
- // POST /stripe_webhook - Handle Stripe webhooks
- // --------------------------------------------------------------------------------
- if ($method === 'POST' && ($hasStripeWebhookParam || strpos($path, '/stripe_webhook') !== false)) {
- $CLICSHOPPING_getRetailers->handleStripeWebhook();
- exit;
- }
- // --------------------------------------------------------------------------------
- // POST /create_order - Create ClicShopping order from session
- // --------------------------------------------------------------------------------
- $hasCreateOrderParam = isset($_GET['create_order']);
- $orderSessionIdParam = isset($_GET['session_id']) ? (string)$_GET['session_id'] : null;
- if ($method === 'POST' && ($hasCreateOrderParam || strpos($path, '/create_order') !== false)) {
- if (empty($orderSessionIdParam)) {
- http_response_code(400);
- echo json_encode(['error' => 'Session ID required']);
- exit;
- }
- // POST /complete_and_order - Complete session then create order
- // --------------------------------------------------------------------------------
- $hasCompleteAndOrderParam = isset($_GET['complete_and_order']);
- $completeSessionIdParam = isset($_GET['session_id']) ? (string)$_GET['session_id'] : null;
- if ($method === 'POST' && ($hasCompleteAndOrderParam || strpos($path, '/complete_and_order') !== false)) {
- if (empty($completeSessionIdParam)) {
- http_response_code(400);
- echo json_encode(['error' => 'Session ID required']);
- exit;
- }
- $hasCheckoutParam = isset($_GET['checkout_sessions']) || isset($_GET['retailers/checkout_sessions']);
- $checkoutIdParam = isset($_GET['id']) ? (string)$_GET['id'] : null;
- $hasCompleteParam = isset($_GET['complete']);
- $hasWebhookParam = isset($_GET['webhook']);
- if ($method === 'GET' && ($hasProductsParam || strpos($path, '/products') !== false)) {
- $filters = [
- 'page' => $_GET['page'] ?? 1,
- 'limit' => $_GET['limit'] ?? 100,
- 'category' => $_GET['category'] ?? null,
- 'min_price' => $_GET['min_price'] ?? null,
- 'action' => 'products'
- ]);
- exit;
- }
- if ($method === 'POST' && ($hasCheckoutParam || strpos($path, '/checkout_sessions') !== false)) {
- if (($hasCompleteParam || strpos($path, '/complete') !== false) && (($checkoutIdParam !== null) || preg_match('#/checkout_sessions/([^/]+)/complete#', $path, $matches))) {
- $sessionId = $checkoutIdParam ?? $matches[1] ?? null;
- if (!$sessionId) {
- $errorResponse('VALIDATION_ERROR', 'Missing session id');
- }
- ]);
- exit;
- }
- if ($method === 'POST' && ($hasCheckoutParam || strpos($path, '/checkout_sessions') !== false)) {
- if (($hasCompleteParam || strpos($path, '/complete') !== false) && (($checkoutIdParam !== null) || preg_match('#/checkout_sessions/([^/]+)/complete#', $path, $matches))) {
- $sessionId = $checkoutIdParam ?? $matches[1] ?? null;
- if (!$sessionId) {
- $errorResponse('VALIDATION_ERROR', 'Missing session id');
- }
- $result = $ucp->completeSession($sessionId, $input);
- 'action' => 'checkout_sessions.update'
- ]);
- exit;
- }
- if ($method === 'POST' && ($hasWebhookParam || strpos($path, '/webhook') !== false)) {
- $result = $ucp->handleWebhook($input);
- echo json_encode($result, JSON_UNESCAPED_SLASHES);
- $logger->info('UCP response', [
- 'request_id' => $requestId,
- 'status' => 200,
- * @return bool True if it contains a comparison operator, false otherwise.
- */
- private function isComparisonClause(string $clause): bool
- {
- foreach (self::ALLOWED_OPERATORS as $operator) {
- if (strpos($clause, $operator) !== false) {
- return true;
- }
- }
- return false;
- }
- while ($Qconfiguration->fetch()) {
- if ($Qconfiguration->hasValue('use_function') && !\is_null($Qconfiguration->value('use_function'))) {
- $use_function = $Qconfiguration->value('use_function');
- if (preg_match('/->/', $use_function)) {
- $class_method = explode('->', $use_function);
- if (!\is_object($class_method[0])) {
- include_once('Core/classes/' . $class_method[0] . '.php');
- ${$class_method[0]} = new $class_method[0]();
- // Register shutdown function to handle timeout gracefully
- register_shutdown_function(function() use ($seconds) {
- $error = error_get_last();
- if ($error && ($error['type'] === E_ERROR || $error['type'] === E_USER_ERROR)) {
- if (strpos($error['message'], 'Maximum execution time') !== false) {
- error_log('[INFO : TIME] TIMEOUT ERROR: Query exceeded ' . $seconds . ' seconds');
- if (ob_get_length()) ob_clean();
- header('Content-Type: application/json; charset=UTF-8');
- define('CLICSHOPPING_APP_CHATGPT_CH_MODEL', 'gpt-5-mini');
- }
- $model = $engine ?? CLICSHOPPING_APP_CHATGPT_CH_MODEL;
- if (strpos($model, 'gpt') === 0) {
- $maxtoken = self::getMaxTokens($maxtoken);
- $temperature = $temperature ?? (float)CLICSHOPPING_APP_CHATGPT_CH_TEMPERATURE;
- $tokenParams = ModelManager::getModelApiParameters($model, $maxtoken);
- if ($engine !== null) {
- $parameters['model'] = $engine;
- }
- $client = ProviderManager::getOpenAiGpt($parameters);
- } elseif (strpos($model, 'anth') === 0) {
- $client = ProviderManager::getAnthropicChat($model, $maxtoken);
- } elseif (strpos($model, 'mistral') === 0) {
- $client = ProviderManager::getMistralChat($model, $maxtoken);
- } elseif (strpos($model, 'ollama') === 0 || str_contains($model, ':latest')) {
- $client = ProviderManager::getOllamaChat($model);
- }
- $client = ProviderManager::getOpenAiGpt($parameters);
- } elseif (strpos($model, 'anth') === 0) {
- $client = ProviderManager::getAnthropicChat($model, $maxtoken);
- } elseif (strpos($model, 'mistral') === 0) {
- $client = ProviderManager::getMistralChat($model, $maxtoken);
- } elseif (strpos($model, 'ollama') === 0 || str_contains($model, ':latest')) {
- $client = ProviderManager::getOllamaChat($model);
- } elseif (strpos($model, 'openai/') === 0) {
- $client = ProviderManager::getLmStudioChat($model);
- $client = ProviderManager::getOpenAiGpt($parameters);
- } elseif (strpos($model, 'anth') === 0) {
- $client = ProviderManager::getAnthropicChat($model, $maxtoken);
- } elseif (strpos($model, 'mistral') === 0) {
- $client = ProviderManager::getMistralChat($model, $maxtoken);
- } elseif (strpos($model, 'ollama') === 0 || str_contains($model, ':latest')) {
- $client = ProviderManager::getOllamaChat($model);
- } elseif (strpos($model, 'openai/') === 0) {
- $client = ProviderManager::getLmStudioChat($model);
- } else {
- $client = ProviderManager::getLmStudioChat($model);
- $client = ProviderManager::getAnthropicChat($model, $maxtoken);
- } elseif (strpos($model, 'mistral') === 0) {
- $client = ProviderManager::getMistralChat($model, $maxtoken);
- } elseif (strpos($model, 'ollama') === 0 || str_contains($model, ':latest')) {
- $client = ProviderManager::getOllamaChat($model);
- } elseif (strpos($model, 'openai/') === 0) {
- $client = ProviderManager::getLmStudioChat($model);
- } else {
- $client = ProviderManager::getLmStudioChat($model);
- }
- if (is_null($temperature)) {
- $temperature = 0.5;
- }
- if (strpos(CLICSHOPPING_APP_CHATGPT_CH_MODEL, 'gpt') === 0) {
- $engine = CLICSHOPPING_APP_CHATGPT_CH_MODEL;
- $response = Gpt::getGptResponse($question, $maxtoken, $temperature, $engine);
- } else {
- //ollama
- $response = Gpt::getGptResponse($question, $maxtoken, $temperature);
- // Simple routing
- // --------------------------------------------------------------------------------
- // GET /products - Returns product catalog
- // --------------------------------------------------------------------------------
- if ($method === 'GET' && ($hasProductsParam || strpos($path, '/products') !== false)) {
- // Return full product catalog
- $products = $CLICSHOPPING_getRetailers->getProducts();
- echo json_encode(['products' => $products], JSON_UNESCAPED_SLASHES);
- exit;
- } elseif (!empty($checkoutIdParam)) {
- // Fallback ou prise en compte du paramètre 'id' si l'ID n'est pas dans le chemin
- $sessionId = $checkoutIdParam;
- }
- if ($method === 'POST' && ($hasCheckoutParam || strpos($path, '/checkout_sessions') !== false)) {
- if ($sessionId) {
- // Completion: POST /checkout_sessions/{id}
- // Choose Delegated Payment or Stripe based on payload
- if (!empty($input['delegated_payment'])) {
- $session = $CLICSHOPPING_getRetailers->completeSessionWithDelegatedPayment($sessionId, $input);
- exit;
- }
- // --------------------------------------------------------------------------------
- // POST /stripe_webhook - Handle Stripe webhooks
- // --------------------------------------------------------------------------------
- if ($method === 'POST' && ($hasStripeWebhookParam || strpos($path, '/stripe_webhook') !== false)) {
- $CLICSHOPPING_getRetailers->handleStripeWebhook();
- exit;
- }
- // --------------------------------------------------------------------------------
- // POST /create_order - Create ClicShopping order from session
- // --------------------------------------------------------------------------------
- $hasCreateOrderParam = isset($_GET['create_order']);
- $orderSessionIdParam = isset($_GET['session_id']) ? (string)$_GET['session_id'] : null;
- if ($method === 'POST' && ($hasCreateOrderParam || strpos($path, '/create_order') !== false)) {
- if (empty($orderSessionIdParam)) {
- http_response_code(400);
- echo json_encode(['error' => 'Session ID required']);
- exit;
- }
- // POST /complete_and_order - Complete session then create order
- // --------------------------------------------------------------------------------
- $hasCompleteAndOrderParam = isset($_GET['complete_and_order']);
- $completeSessionIdParam = isset($_GET['session_id']) ? (string)$_GET['session_id'] : null;
- if ($method === 'POST' && ($hasCompleteAndOrderParam || strpos($path, '/complete_and_order') !== false)) {
- if (empty($completeSessionIdParam)) {
- http_response_code(400);
- echo json_encode(['error' => 'Session ID required']);
- exit;
- }
- while ($Qconfiguration->fetch()) {
- if ($Qconfiguration->hasValue('use_function') && !\is_null($Qconfiguration->value('use_function'))) {
- $use_function = $Qconfiguration->value('use_function');
- if (preg_match('/->/', $use_function)) {
- $class_method = explode('->', $use_function);
- if (!\is_object($class_method[0])) {
- include_once('Core/classes/' . $class_method[0] . '.php');
- $class_method[0] = new $class_method[0]();
- $module_active = $modules_payment;
- $include_modules = [];
- foreach ($modules_payment as $value) {
- if (strpos($value, '\\') !== false) {
- $class = Apps::getModuleClass($value, 'Payment');
- $include_modules[] = ['class' => $value,
- 'file' => $class
- ];
- ];
- }
- }
- for ($i = 0, $n = \count($include_modules); $i < $n; $i++) {
- if (strpos($include_modules[$i]['class'], '\\') !== false) {
- Registry::set('Payment_' . str_replace('\\', '_', $include_modules[$i]['class']), new $include_modules[$i]['file']);
- $module = Registry::get('Payment_' . str_replace('\\', '_', $include_modules[$i]['class']));
- ?>
- <div class="row">
- <div class="col-md-12">
- $module_active = $modules_shipping;
- $include_modules = [];
- foreach ($modules_shipping as $value) {
- if (strpos($value, '\\') !== false) {
- $class = Apps::getModuleClass($value, 'Shipping');
- $include_modules[] = ['class' => $value,
- 'file' => $class
- ];
- ];
- }
- }
- for ($i = 0, $n = \count($include_modules); $i < $n; $i++) {
- if (strpos($include_modules[$i]['class'], '\\') !== false) {
- Registry::set('Shipping_' . str_replace('\\', '_', $include_modules[$i]['class']), new $include_modules[$i]['file']);
- $module = Registry::get('Shipping_' . str_replace('\\', '_', $include_modules[$i]['class']));
- ?>
- <div class="row">
- <div class="col-md-5">
- $basePath = CLICSHOPPING::getConfig('dir_root', 'Shop') . $CLICSHOPPING_Template->getDynamicTemplateDirectory() . '/modules/' . $directory_selected . '/content/';
- $filePath = realpath($basePath . $filename_selected);
- // Sécurité chemin
- if ($filePath === false || strpos($filePath, realpath($basePath)) !== 0 || !is_file($filePath)) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_EditDesign->getDef('error_file_does_not_exist'), 'error');
- $CLICSHOPPING_EditDesign->redirect('EditModuleContent&action=directory&directory_html=' . $directory_selected);
- return false;
- }
- $lang_dir = $CLICSHOPPING_Language->get('directory');
- $basePathLang = CLICSHOPPING::getConfig('dir_root', 'Shop') . $CLICSHOPPING_Template->getDynamicTemplateDirectory() . "/css/{$lang_dir}/{$directory_selected}/";
- $basePathFallback = CLICSHOPPING::getConfig('dir_root', 'Shop') . $CLICSHOPPING_Template->getDynamicTemplateDirectory() . "/css/english/{$directory_selected}/";
- $filePath = realpath($basePathLang . $filename_selected);
- if ($filePath === false || strpos($filePath, realpath($basePathLang)) !== 0 || !is_file($filePath)) {
- $filePath = realpath($basePathFallback . $filename_selected);
- if ($filePath === false || strpos($filePath, realpath($basePathFallback)) !== 0 || !is_file($filePath)) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_EditDesign->getDef('error_file_does_not_exist'), 'error');
- $CLICSHOPPING_EditDesign->redirect('EditCss&action=directory&directory_css=' . $directory_selected);
- return false;
- $basePathFallback = CLICSHOPPING::getConfig('dir_root', 'Shop') . $CLICSHOPPING_Template->getDynamicTemplateDirectory() . "/css/english/{$directory_selected}/";
- $filePath = realpath($basePathLang . $filename_selected);
- if ($filePath === false || strpos($filePath, realpath($basePathLang)) !== 0 || !is_file($filePath)) {
- $filePath = realpath($basePathFallback . $filename_selected);
- if ($filePath === false || strpos($filePath, realpath($basePathFallback)) !== 0 || !is_file($filePath)) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_EditDesign->getDef('error_file_does_not_exist'), 'error');
- $CLICSHOPPING_EditDesign->redirect('EditCss&action=directory&directory_css=' . $directory_selected);
- return false;
- }
- }
- $baseDir = CLICSHOPPING::getConfig('dir_root', 'Shop') . $CLICSHOPPING_Template->getDynamicTemplateDirectory() . '/files/';
- $filePath = realpath($baseDir . $filename_selected);
- // Sécuriser le chemin pour éviter directory traversal
- if ($filePath === false || strpos($filePath, realpath($baseDir)) !== 0) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_EditDesign->getDef('error_file_does_not_exist'), 'error');
- $CLICSHOPPING_EditDesign->redirect('EditModuleContent&action=directory&directory_html=' . $directory_selected);
- return false;
- }
- . $CLICSHOPPING_Template->getDynamicTemplateDirectory()
- . '/modules/' . $directory_selected . '/template_html/';
- $filePath = realpath($basePath . $filename_selected);
- if ($filePath === false || strpos($filePath, realpath($basePath)) !== 0 || !is_file($filePath)) {
- $CLICSHOPPING_MessageStack->add($CLICSHOPPING_EditDesign->getDef('error_file_does_not_exist'), 'error');
- $CLICSHOPPING_EditDesign->redirect('EditListing&action=directory&directory_html=' . $directory_selected);
- return false;
- }
- $Qcategories->execute();
- $categories_array = $Qcategories->fetchAll();
- foreach ($categories_array as $cat) {
- $catLower = strtolower($cat['categories_name'] ?? '');
- if (strpos($translated, $catLower) !== false) {
- $intent['entities']['category'] = $catLower;
- $matchWeight += 0.8;
- $totalWeight += 1;
- break;
- }
- 'text' => $Qproducts->valueInt('customers_basket_quantity') . ' x ' . $Qproducts->value('products_name')
- ];
- $attributes = [];
- if (strpos($Qproducts->valueInt('products_id'), '{') !== false) {
- $combos = [];
- preg_match_all('/(\{[0-9]+\}[0-9]+){1}/', $Qproducts->valueInt('products_id'), $combos);
- foreach ($combos[0] as $combo) {
- $att = [];
- 'Connection' => 'close'
- ];
- if (!empty($parameters['header'])) {
- foreach ($parameters['header'] as $header) {
- if (strpos($header, ':') !== false) {
- [$name, $value] = explode(':', $header, 2);
- $headers[trim($name)] = trim($value);
- }
- }
- }
- $headers = ['status_code' => $statusCode];
- while (($line = fgets($socket)) !== false) {
- $line = trim($line);
- if ($line === '') break;
- if (strpos($line, ':') !== false) {
- [$name, $value] = explode(':', $line, 2);
- $headers[strtolower(trim($name))] = trim($value);
- }
- }
- foreach ($files as $sm) {
- $result['file'][] = ['files_name' => $sm];
- }
- foreach ($result['file'] as &$module) {
- if (strpos($module['files_name'], '.') !== false) {
- $class = substr($module['files_name'], 0, strrpos($module['files_name'], '.'));
- $this->startService($class);
- }
- }
- }
- $content = file($spiders_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
- foreach ($content as $line) {
- $line = trim($line);
- // Ignore empty lines and comments starting with '#'
- if (!empty($line) && strpos($line, '#') !== 0) {
- $spiders_array[] = strtolower($line);
- }
- }
- // Save processed list to cache for future requests
- $this->logSecurityError("Invalid path detected", $path);
- continue;
- }
- // Ensure the resolved path is still within the root directory
- if (strpos($real_path, $root_dir) !== 0) {
- $this->logSecurityError("Path traversal attempt detected", $real_path);
- continue;
- }
- if (is_file($real_path) && is_readable($real_path)) {
- if ((substr($spider, strlen($spider) - 1, 1) == ' ') || (substr($spider, strlen($spider) - 1, 1) == "\n")) {
- $spider = substr($spider, 0, strlen($spider) - 1);
- }
- if (!empty($spider)) {
- if (strpos($user_agent, $spider) !== false) {
- $parameters['can_start'] = false;
- break;
- }
- }
- }
- // Also clear old embedding cache files from root cache directory (excluding embedding_search)
- $oldEmbeddingFiles = glob($generalCacheDir . 'embedding_*.cache');
- if ($oldEmbeddingFiles) {
- // Filter out embedding_search files
- $oldEmbeddingFiles = array_filter($oldEmbeddingFiles, function($file) {
- return strpos(basename($file), 'embedding_search_') !== 0;
- });
- $cleared = 0;
- foreach ($oldEmbeddingFiles as $file) {
- if (unlink($file)) {
- $CLICSHOPPING_templateCss->logSecurityError("CSS file not accessible", $cssFile);
- continue;
- }
- // Directory Traversal protection: ensure the file is within the allowed root directory
- if (strpos($real_path, $root_dir . DIRECTORY_SEPARATOR) !== 0) {
- $CLICSHOPPING_templateCss->logSecurityError("CSS file outside allowed directory", $cssFile);
- continue;
- }
- // Check individual file size
Your project uses legacy callable syntax instead of first-class callable syntax 5
- Read doc
- Productivity
- Info
More information: https://insight.symfony.com/what-we-analyse/php.use_first_class_callable_syntax
- $config = [];
- foreach ($embeddingTables as $embeddingTable) {
- // Extract entity type: clic_products_embedding -> products
- $entityType = str_replace([$prefix, '_embedding'], '', $embeddingTable);
- $table = $prefix . $entityType;
- // Get ID column from EntityRegistry (reuse existing logic)
- $idColumn = $entityRegistry->getIdColumnForEntityType($entityType);
- $config = [];
- foreach ($embeddingTables as $embeddingTable) {
- // Extract entity type: clic_products_embedding -> products
- $entityType = str_replace([$prefix, '_embedding'], '', $embeddingTable);
- $table = $prefix . $entityType;
- // Get ID column from EntityRegistry (reuse existing logic)
- $idColumn = $entityRegistry->getIdColumnForEntityType($entityType);
- * @return string
- */
- private function normalizeTableName(string $fullTableName): string
- {
- $prefix = CLICSHOPPING::getConfig('db_table_prefix');
- return str_replace([$prefix, '_embedding'], '', $fullTableName);
- }
- /**
- * Attempts to extract entity_type from SQL query by analyzing table names
- *
- }
- $prefix = CLICSHOPPING::getConfig('db_table_prefix');
- // Remove prefix and '_embedding' suffix to get entity type
- $entityType = str_replace([$prefix, '_embedding'], '', $tableName);
- // Get ID column for this entity type
- $idColumn = $this->getIdColumnForEntityType($entityType);
- // Cache the result
- public function getEntityTypeForTable(string $tableName): string
- {
- $prefix = CLICSHOPPING::getConfig('db_table_prefix');
- // Remove prefix and '_embedding' suffix
- $entityType = str_replace([$prefix, '_embedding'], '', $tableName);
- return $entityType;
- }
- /**
gyakutsuki