From a3fd9b78d0361730edccc330679dfbd8ddff77d7 Mon Sep 17 00:00:00 2001 From: ldestailleur Date: Mon, 3 Mar 2025 20:10:39 +0100 Subject: [PATCH] Debug v22 --- htdocs/admin/modules.php | 44 ++- .../class/externalModules.class.php | 156 +++++---- htdocs/theme/dolibarr_logo.svg | 300 +++++++----------- 3 files changed, 238 insertions(+), 262 deletions(-) diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 3ee3e0269122e..252b9d6541918 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -98,8 +98,10 @@ $options['search_source_github'] = 1; } -//$remotestore = new Dolistore(false); -$remotestore = new ExternalModules(); +//$remotestore = new Dolistore(false); +$remotestore = new ExternalModules(); +$remotestore->loadRemoteSources(); + if (!$user->admin) { accessforbidden(); @@ -484,7 +486,6 @@ - /* * View */ @@ -1264,6 +1265,8 @@ print '
'; + print ''; + // Marketplace and community modules print '
'; print ''."\n"; @@ -1277,19 +1280,38 @@ // Marketplace print ''."\n"; $url = 'https://www.dolistore.com'; - print ''; + print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; // Community print ''."\n"; $url = 'https://github.com/Dolibarr/dolibarr-community-modules'; - print ''; + print ''; print ''; - print ''; - print ''; + print ''; + print ''; print ''; print "
'.$langs->trans("DoliStoreDesc").''.$url.'' . $remotestore->libStatut($remotestore->dolistoreApiStatus).''.img_picto('', 'url', 'class="pictofixedwidth"').''.$url.''; + if (!getDolGlobalString('MAIN_DISABLE_DOLISTORE_SEARCH') && getDolGlobalInt('MAIN_ENABLE_DOLISTORE')) { + $messagetoadd = ''; + if ($remotestore->dolistoreApiStatus <= 0) { + $messagetoadd = '
'.$remotestore->dolistoreApiError.'
Failed to login to: '.$remotestore->dolistore_api_url; + $messagetoadd .= '
using API public key: '.$remotestore->dolistore_api_key; + // Add basic auth if needed + $basicAuthLogin = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_LOGIN'); + $basicAuthPassword = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_PASSWORD'); + if ($basicAuthLogin) { + $messagetoadd .= '
using basic auth login: base64('.$basicAuthLogin.':'.$basicAuthPassword.')'; + } + } + print $remotestore->libStatus($remotestore->dolistoreApiStatus, 2, $messagetoadd); + } + print '
'.$langs->trans("CommunityModulesDesc").''.$url.'' . $remotestore->libStatut($remotestore->githubFileStatus) . ''.img_picto('', 'url', 'class="pictofixedwidth"').''.$url.''; + if (!getDolGlobalString('MAIN_DISABLE_DOLISTORE_SEARCH') && getDolGlobalInt('MAIN_ENABLE_COMMUNITY_REPO')) { + print $remotestore->libStatus($remotestore->githubFileStatus, 2, '
Content of repository file '.$remotestore->file_source_url.' is in the cache file '.$remotestore->cache_file.''); + } + print '
\n"; @@ -1301,10 +1323,10 @@ $conf->global->MAIN_DISABLE_DOLISTORE_SEARCH = 0; // avoid warning with the new Dolistore website - if (!getDolGlobalString('MAIN_DISABLE_DOLISTORE_SEARCH') && getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 && $remotestore->numberOfProviders > 0) { + if (!getDolGlobalString('MAIN_DISABLE_DOLISTORE_SEARCH') && $remotestore->numberOfProviders > 0) { // $options is array with filter criteria - if (getDolGlobalInt('MAIN_ENANLE_OLD_DOLISTORE')) { + if (getDolGlobalInt('MAIN_ENABLE_DOLISTORE')) { $nbmaxtoshow = $options['per_page']; $options['per_page']++; diff --git a/htdocs/admin/remotestore/class/externalModules.class.php b/htdocs/admin/remotestore/class/externalModules.class.php index cdb0362ca0a9b..fa0e87fb49038 100644 --- a/htdocs/admin/remotestore/class/externalModules.class.php +++ b/htdocs/admin/remotestore/class/externalModules.class.php @@ -110,6 +110,7 @@ class ExternalModules */ public $products; + /** * Constructor * @@ -119,29 +120,41 @@ public function __construct($debug = false) { global $langs; - $cachedelayforgithubrepo = getDolGlobalInt('MAIN_REMOTE_GITHUBREPO_CACHE_DELAY', 86400); - $this->dolistore_api_url = getDolGlobalString('MAIN_MODULE_DOLISTORE_API_SRV'); $this->dolistore_api_key = getDolGlobalString('MAIN_MODULE_DOLISTORE_API_KEY'); $this->url = DOL_URL_ROOT.'/admin/modules.php?mode=marketplace'; $this->shop_url = 'https://www.dolistore.com/product.php?id='; + $this->debug_api = $debug; $this->file_source_url = "https://raw.githubusercontent.com/Dolibarr/dolibarr-community-modules/refs/heads/main/index.yaml"; $this->cache_file = DOL_DATA_ROOT.'/admin/temp/remote_github_modules_file.yaml'; - $this->getRemoteYamlFile($this->file_source_url, $cachedelayforgithubrepo); - $lang = $langs->defaultlang; $lang_array = array('en_US', 'fr_FR', 'es_ES', 'it_IT', 'de_DE'); if (!in_array($lang, $lang_array)) { $lang = 'en_US'; } $this->lang = $lang; + } + + /** + * loadRemoteSources + * + * @param boolean $debug Enable debug of request on screen + * @return void + */ + public function loadRemoteSources($debug = false) + { + $cachedelayforgithubrepo = getDolGlobalInt('MAIN_REMOTE_GITHUBREPO_CACHE_DELAY', 86400); + + $this->getRemoteYamlFile($this->file_source_url, $cachedelayforgithubrepo); + // Check access to Dolistore API $this->dolistoreApiStatus = $this->checkApiStatus(); + $this->githubFileStatus = dol_is_file($this->cache_file) ? 1 : 0; // Count the number of online providers @@ -153,7 +166,6 @@ public function __construct($debug = false) * * @param string $resource Resource name * @param array|false $options Options for the request - * * @return array{status_code:int,response:null|string|array,header:string} */ public function callApi($resource, $options = false) @@ -164,52 +176,29 @@ public function callApi($resource, $options = false) return array('status_code' => 0, 'response' => null, 'header' => ''); } - $curl = curl_init(); - $httpheader = ['DOLAPIKEY: '.$this->dolistore_api_key]; - // Add basic auth if needed $basicAuthLogin = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_LOGIN'); $basicAuthPassword = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_PASSWORD'); - if (!empty($basicAuthLogin) && !empty($basicAuthPassword)) { - curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - $login = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_LOGIN'); - $password = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_PASSWORD'); - curl_setopt($curl, CURLOPT_USERPWD, $login . ':' . $password); + $httpheader = array('DOLAPIKEY: '.$this->dolistore_api_key); + if ($basicAuthLogin) { + $httpheader[] = 'Authorization: Basic '.base64_encode($basicAuthLogin.':'.$basicAuthPassword); } - $url = $this->dolistore_api_url . $resource; + $url = $this->dolistore_api_url . (preg_match('/\/$/', $this->dolistore_api_url) ? '' : '/') . $resource; if ($options) { $url .= '?' . http_build_query($options); } - curl_setopt($curl, CURLOPT_URL, $url); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_HTTPHEADER, $httpheader); - curl_setopt($curl, CURLOPT_HEADER, true); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); + $response = getURLContent($url, 'POST', '', 1, $httpheader); - $response = curl_exec($curl); + $body = $response['content']; + $body = json_decode($body, true); - if ($response === false) { - return array('status_code' => 0, 'response' => 'CURL Error: ' . curl_error($curl), 'header' => ''); - } - - $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); - $header = substr($response, 0, $header_size); - $body = substr($response, $header_size); - - // convert body to array if it is json - if (strpos($header, 'Content-Type: application/json') !== false) { - $body = json_decode($body, true); - } - - $status_code = curl_getinfo($curl, CURLINFO_HTTP_CODE); - curl_close($curl); + $status_code = $response['http_code']; - return array('status_code' => $status_code, 'response' => $body, 'header' => $header); + return array('status_code' => $status_code, 'response' => $body); } /** @@ -321,8 +310,8 @@ public function getProducts($options) // fetch from github repo $fileProducts = array(); if (!empty($this->githubFileStatus) && $options['search_source_github'] == 1) { - $fileProducts = $this->fetchModulesFromFile($data); - $fileProducts = $this->adaptData($fileProducts, 'github'); + $fileProducts = $this->fetchModulesFromFile($data); // Return an array with all modules from the cache filecontent in $data + $fileProducts = $this->adaptData($fileProducts, 'githubcommunity'); $fileProducts = $this->applyFilters($fileProducts, $data); } @@ -374,14 +363,24 @@ static function ($a, $b) { } else { $download_link = '#'; $price = '

'.$langs->trans('Free').'

'; - if ($product['source'] === 'Dolistore') { - $download_link = ''; - $download_link .= ''; - } - if ($product['source'] === 'Github') { + if ($product['source'] === 'githubcommunity') { $download_link = ''; - $download_link .= ''; + if (!empty($product['direct-download']) && $product['direct-download'] == 'yes') { + $urldownload = $product["dolistore-download"]; // In a future, we will have the download to the zip file + $reg = array(); + if (preg_match('/https:.*\?id=(\d+)$/', $urldownload, $reg)) { + $urldownload = 'https://www.dolistore.com/_service_download.php?t=free&p='.$reg[1]; + } + $download_link .= ''; + } + } + + if ($product['source'] === 'dolistore') { + $download_link = ''; + if (!empty($product['direct-download']) && $product['direct-download'] == 'yes') { + $download_link .= ''; + } } } @@ -428,7 +427,15 @@ static function ($a, $b) { $html .= '
'; $html .= $version; // No dol_escape_htmltag, it is already escape html $html .= ''; - $html .= ' '.dol_print_date(dol_stringtotime($product['tms']), 'day').' - '.$langs->trans('Ref').': '.dol_escape_htmltag($product["ref"]).' - '.dol_escape_htmltag($langs->trans('Id')).': '.((int) $product["id"]).'
'; + $html .= ' '; + if (empty($product['tms'])) { + $html .= ''.$langs->trans("DateCreation").': '.$langs->trans("Unknown").''; + } else { + $html .= dol_print_date(dol_stringtotime($product['tms']), 'day'); + } + $html .= ' - '.$langs->trans('Ref').' '.dol_escape_htmltag($product["ref"]); + //$html .= ' - '.dol_escape_htmltag($langs->trans('Id')).': '.((int) $product["id"]); + $html .= '
'; $html .= ''.$langs->trans('Source').': '.$product["source"].'
'; $html .= '
'.dol_escape_htmltag(dol_string_nohtmltag($product["description"])); $html .= ''; @@ -632,11 +639,11 @@ protected function checkStatusCode($request) } /** - * get YAML file from remote source and put it in cache file for one day - * @param string $file_source_url URL of the remote source - * @param int $cache_time Cache time + * Get YAML file from remote source and put it into the cache file * - * @return string Uri of the cache file + * @param string $file_source_url URL of the remote source + * @param int $cache_time Cache time + * @return string Uri of the cache file */ public function getRemoteYamlFile($file_source_url, $cache_time) { @@ -649,13 +656,17 @@ public function getRemoteYamlFile($file_source_url, $cache_time) } if (!file_exists($cache_file) || filemtime($cache_file) < (dol_now() - $cache_time)) { - $yaml = file_get_contents($file_source_url); - if (!empty($yaml)) { + // We get remote url + $result = getURLContent($file_source_url); + if (!empty($result) && $result['http_code'] == 200) { + $yaml = $result['content']; file_put_contents($cache_file, $yaml); } + } else { + $yaml = file_get_contents($cache_file); } - return $cache_file; + return $yaml; } @@ -680,6 +691,7 @@ public function readYaml($yaml) } // Match a new package entry (e.g., "- modulename: 'helloasso'") + $matches = array(); if (preg_match('/^\s*-\s*modulename:\s*["\']?(.*?)["\']?$/', $trimmedLine, $matches)) { if ($currentPackage !== null) { $data[] = $currentPackage; @@ -740,7 +752,7 @@ public function adaptData($data, $source) return $adaptedData; } - if ($source === 'github') { + if ($source === 'githubcommunity') { foreach ($data as $package) { if (empty($package['modulename'])) { continue; @@ -766,6 +778,12 @@ public function adaptData($data, $source) 'dolibarr_max' => !empty($package['dolibarrmax']) ? $package['dolibarrmax'] : 'unknown', + 'phpmin' => !empty($package['phpmin']) + ? $package['phpmin'] + : 'unknown', + 'phpmax' => !empty($package['phpmax']) + ? $package['phpmax'] + : 'unknown', 'module_version' => !empty($package['current_version']) ? $package['current_version'] : 'unknown', @@ -778,7 +796,13 @@ public function adaptData($data, $source) 'link' => !empty($package['git']) ? $package['git'] : '#', - 'source' => 'Github' + 'source' => 'githubcommunity', + 'direct-download' => !empty($package['direct-download']) + ? $package['direct-download'] + : '', + 'dolistore-download' => !empty($package['dolistore-download']) + ? $package['dolistore-download'] + : '', ]; $adaptedData[] = $adaptedPackage; @@ -797,9 +821,11 @@ public function adaptData($data, $source) 'price_ttc' => $package['price_ttc'], 'dolibarr_min' => $package['dolibarr_min'], 'dolibarr_max' => $package['dolibarr_max'], + 'phpmin' => $package['phpmin'], + 'phpmax' => $package['phpmax'], 'module_version' => $package['module_version'], 'cover_photo_url' => $urldolibarrmodules.$package['cover_photo_url'], - 'source' => 'Dolistore' + 'source' => 'dolistore' ]; $adaptedData[] = $adaptedPackage; @@ -881,7 +907,6 @@ static function ($package) use ($options) { */ public function checkApiStatus() { - $testRequest = $this->callApi('categories'); if (!isset($testRequest['response']) || !is_array($testRequest['response']) || ($testRequest['status_code'] != 200 && $testRequest['status_code'] != 201)) { @@ -894,28 +919,29 @@ public function checkApiStatus() /** * Retrieve the status icon - * @param mixed $status Status - * @param mixed $mode Mode * - * @return string + * @param mixed $status Status + * @param mixed $mode Mode + * @param string $moretext More text to show on tooltip + * @return string */ - public function libStatut($status, $mode = 3) + public function libStatus($status, $mode = 3, $moretext = '') { global $langs; $statusType = 'status4'; if ($status == 0) { - $statusType = 'status6'; + $statusType = 'status8'; } $labelStatus = []; $labelStatusShort = []; - $labelStatus[0] = $this->dolistoreApiError; + $labelStatus[0] = $langs->transnoentitiesnoconv("offline"); $labelStatus[1] = $langs->transnoentitiesnoconv("online"); - $labelStatusShort[0] = $this->dolistoreApiError; + $labelStatusShort[0] = $langs->transnoentitiesnoconv("offline"); $labelStatusShort[1] = $langs->transnoentitiesnoconv("online"); - return dolGetStatus($labelStatus[$status], $labelStatusShort[$status], '', $statusType, $mode); + return dolGetStatus($labelStatus[$status], $labelStatusShort[$status], '', $statusType, $mode, '', array('badgeParams' => array('attr' => array('class' => 'classfortooltip', 'title' => $labelStatusShort[$status].$moretext)))); } } diff --git a/htdocs/theme/dolibarr_logo.svg b/htdocs/theme/dolibarr_logo.svg index 9c9259d0b3305..72795dfbbe7fd 100644 --- a/htdocs/theme/dolibarr_logo.svg +++ b/htdocs/theme/dolibarr_logo.svg @@ -2,39 +2,49 @@ - Logo Dolibarr ERP-CRM - - - - - - - - - - - - - - - image/svg+xml - - Logo Dolibarr ERP-CRM - - - - Laurent Destailleur - - - - - Laurent Destailleur - - - - - - - - - - - - - - - - - - - - - - - - - - - ERP/CRM - - - + id="layer1" + transform="translate(-11.600433,-16.785229)">ERP/CRM