450 lines
15 KiB
PHP
450 lines
15 KiB
PHP
<?php
|
||
/**
|
||
* The model file of store module of QuCheng.
|
||
*
|
||
* @copyright Copyright 2021-2022 北京渠成软件有限公司(Beijing QuCheng Software Co,LTD, www.qucheng.com)
|
||
* @license ZPL (http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||
* @author Jianhua Wang <wangjanhua@easycorp.ltd>
|
||
* @package store
|
||
* @version $Id$
|
||
* @link https://www.qucheng.com
|
||
*/
|
||
class storeModel extends model
|
||
{
|
||
/**
|
||
* Construct function: set api headers.
|
||
*
|
||
* @param string $appName
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
public function __construct($appName = '')
|
||
{
|
||
parent::__construct($appName);
|
||
|
||
global $config, $app;
|
||
$config->cloud->api->headers[] = "{$config->cloud->api->auth}: {$config->cloud->api->token}";
|
||
|
||
if($config->cloud->api->switchChannel && $app->session->cloudChannel) $config->cloud->api->channel = $app->session->cloudChannel;
|
||
}
|
||
|
||
/**
|
||
* Get app list from cloud market.
|
||
*
|
||
* @param string $keyword
|
||
* @param array $categories
|
||
* @param int $page
|
||
* @param int $pageSize
|
||
* @access public
|
||
* @return object
|
||
*/
|
||
public function searchApps($sortBy = '', $keyword = '', $categories = array(), $page = 1, $pageSize = 20)
|
||
{
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/applist?channel='. $this->config->cloud->api->channel;
|
||
$apiUrl .= "&q=" . rawurlencode(trim($keyword));
|
||
$apiUrl .= "&sort=" . rawurlencode(trim($sortBy));
|
||
$apiUrl .= "&page=$page";
|
||
$apiUrl .= "&page_size=$pageSize";
|
||
foreach($categories as $category) $apiUrl .= "&category=$category"; // The names of category are same that reason is CNE api is required.
|
||
|
||
$result = commonModel::apiGet($apiUrl, array(), $this->config->cloud->api->headers);
|
||
if($result->code == 200) return $result->data;
|
||
|
||
$pagedApps = new stdclass;
|
||
$pagedApps->apps = array();
|
||
$pagedApps->total = 0;
|
||
return $pagedApps;
|
||
}
|
||
|
||
/**
|
||
* Get app info by App chart from cloud market.
|
||
*
|
||
@param string $chart
|
||
* @param string $channel
|
||
* @param bool $analysis
|
||
* @param string $version
|
||
* @access public
|
||
* @return object|null
|
||
*/
|
||
public function getAppInfoByChart($chart, $channel, $analysis, $version = '')
|
||
{
|
||
return $this->getAppInfo(0, $analysis, $chart, $version, $channel);
|
||
}
|
||
|
||
/**
|
||
* Get app info from cloud market.
|
||
*
|
||
* @param int $id
|
||
* @param boolean $analysis true: log this request for analysis.
|
||
* @param string $name
|
||
* @param string $version
|
||
* @param string $channel
|
||
* @access public
|
||
* @return object|null
|
||
*/
|
||
public function getAppInfo($id, $analysis = false, $name = '', $version ='', $channel = '')
|
||
{
|
||
if(empty($id)) return null;
|
||
$apiParams = array();
|
||
$apiParams['analysis'] = $analysis ? 'true' : 'false' ;
|
||
|
||
if($id) $apiParams['id'] = $id;
|
||
if($name) $apiParams['name'] = $name;
|
||
if($version) $apiParams['version'] = $version;
|
||
if($channel) $apiParams['channel'] = $channel;
|
||
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/appinfo';
|
||
$result = commonModel::apiGet($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||
if(!isset($result->code) || $result->code != 200) return null;
|
||
|
||
return $result->data;
|
||
}
|
||
|
||
/**
|
||
* Get app infos map by name array from cloud market.
|
||
* 根据名称查询多个应用信息。
|
||
*
|
||
* @param array $nameList
|
||
* @access public
|
||
* @return object|null
|
||
*/
|
||
public function getAppMapByNames($nameList = array(), $channel = 'stable')
|
||
{
|
||
$apiParams = array('name_list' => $nameList, 'channel' => $channel);
|
||
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/app_info_list';
|
||
$result = commonModel::apiPost($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||
if(!isset($result->code) || $result->code != 200) return null;
|
||
|
||
return $result->data;
|
||
}
|
||
|
||
/**
|
||
* Get app version pairs by id.
|
||
*
|
||
* @param int $id
|
||
* @access public
|
||
* @return array
|
||
*/
|
||
public function getVersionPairs(int $id): array
|
||
{
|
||
$pairs = array();
|
||
$versions = $this->appVersionList($id);
|
||
|
||
foreach($versions as $version) $pairs[$version->version] = $version->app_version . '-' . $version->version;
|
||
|
||
return $pairs;
|
||
}
|
||
|
||
/**
|
||
* Get app version list to install.
|
||
*
|
||
* @param int $id
|
||
* @param string $name
|
||
* @param string $channel
|
||
* @param int $page
|
||
* @param int $pageSize
|
||
* @access public
|
||
* @return mixed
|
||
*/
|
||
public function appVersionList($id, $name = '', $channel = '', $page = 1, $pageSize = 3)
|
||
{
|
||
$apiParams = array();
|
||
$apiParams['page'] = $page;
|
||
$apiParams['page_size'] = $pageSize;
|
||
|
||
if($id) $apiParams['id'] = $id;
|
||
if($name) $apiParams['name'] = $name;
|
||
if($channel) $apiParams['channel'] = $channel;
|
||
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/app/version';
|
||
$result = commonModel::apiGet($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||
if(!isset($result->code) || $result->code != 200) return array();
|
||
|
||
return array_combine(helper::arrayColumn($result->data, 'version'), $result->data);
|
||
}
|
||
|
||
/**
|
||
* Get upgradable versions of app from cloud market.
|
||
*
|
||
* @param string $currentVersion
|
||
* @param int $appID appID is required if no appName.
|
||
* @param string $appName appName is required if no appID.
|
||
* @param string $channel
|
||
* @access public
|
||
* @return mixed
|
||
*/
|
||
public function getUpgradableVersions($currentVersion, $appID = 0, $appName = '', $channel = '')
|
||
{
|
||
$channel = $channel ? $channel : $this->config->cloud->api->channel;
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/app/version/upgradable';
|
||
|
||
$conditions = array('version' => $currentVersion, 'channel' => $channel);
|
||
if($appID)
|
||
{
|
||
$conditions['id'] = $appID;
|
||
}
|
||
else
|
||
{
|
||
$conditions['name'] = $appName;
|
||
}
|
||
|
||
$result = commonModel::apiGet($apiUrl, $conditions, $this->config->cloud->api->headers);
|
||
if(!isset($result->code) || $result->code != 200) return array();
|
||
|
||
return $result->data;
|
||
}
|
||
|
||
/**
|
||
* Get the latest version of QuCheng platform.
|
||
*
|
||
* @access public
|
||
* @return object
|
||
*/
|
||
public function platformLatestVersion()
|
||
{
|
||
$versionList = $this->getUpgradableVersions($this->config->platformVersion, 0, $this->config->edition == 'open' ? 'qucheng' : 'qucheng-biz', $this->config->cloud->api->channel);
|
||
|
||
$latestVersion = $this->pickHighestVersion($versionList);
|
||
if(!empty($latestVersion) && version_compare(str_replace('-', '.', $latestVersion->version), str_replace('-', '.', $this->config->platformVersion), '>')) return $latestVersion;
|
||
|
||
$latestVersion = new stdclass;
|
||
$latestVersion->app_version = getenv('APP_VERSION');
|
||
$latestVersion->version = $this->config->platformVersion;
|
||
|
||
return $latestVersion;
|
||
}
|
||
|
||
/**
|
||
* Get the latest versions of app from cloud market.
|
||
*
|
||
* @param int $appID
|
||
* @param string $currentVersion
|
||
* @access public
|
||
* @return object|null
|
||
*/
|
||
public function appLatestVersion($appID, $currentVersion)
|
||
{
|
||
$versionList = $this->getUpgradableVersions($currentVersion, $appID);
|
||
|
||
$latestVersion = $this->pickHighestVersion($versionList);
|
||
if(empty($latestVersion)) return null;
|
||
|
||
if(version_compare(str_replace('-', '.', $latestVersion->version), str_replace('-', '.', $currentVersion), '>')) return $latestVersion;
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Pick highest version from version list and compared version.
|
||
*
|
||
* @param array $versionList
|
||
* @access private
|
||
* @return object|null
|
||
*/
|
||
private function pickHighestVersion($versionList)
|
||
{
|
||
if(empty($versionList)) return null;
|
||
|
||
$highestVersion = new stdclass;
|
||
$highestVersion->version = '0.0.0';
|
||
foreach($versionList as $version)
|
||
{
|
||
if(version_compare(str_replace('-', '.', $version->version), str_replace('-', '.', $highestVersion->version), '>')) $highestVersion = $version;
|
||
}
|
||
|
||
return $highestVersion;
|
||
}
|
||
|
||
/**
|
||
* Get app setting from cloud market.
|
||
*
|
||
* @param int $id
|
||
* @access public
|
||
* @return array
|
||
*/
|
||
public function getAppSettings($id)
|
||
{
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/appsettings';
|
||
$result = commonModel::apiGet($apiUrl, array('id' => $id), $this->config->cloud->api->headers);
|
||
if($result->code != 200) return array();
|
||
|
||
/* Convert "." to "_" */
|
||
$components = $result->data->components;
|
||
foreach($result->data->components as &$component)
|
||
{
|
||
foreach($component->settings as $setting) $setting->field = str_replace('.', '_', $setting->field);
|
||
}
|
||
|
||
return $components;
|
||
}
|
||
|
||
/**
|
||
* Get category list from cloud market.
|
||
*
|
||
* @access public
|
||
* @return object
|
||
*/
|
||
public function getCategories()
|
||
{
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/categories';
|
||
$result = commonModel::apiGet($apiUrl, array(), $this->config->cloud->api->headers);
|
||
if($result->code == 200) return $result->data;
|
||
|
||
$categories = new stdclass;
|
||
$categories->categories = array();
|
||
$categories->total = 0;
|
||
return $categories;
|
||
}
|
||
|
||
/**
|
||
* Get switcher of browse page of store.
|
||
*
|
||
* @access public
|
||
* @return string
|
||
*/
|
||
public function getBrowseSwitcher()
|
||
{
|
||
$title = $this->lang->store->cloudStore;
|
||
|
||
if($this->config->cloud->api->switchChannel) $title .= '(' . ($this->config->cloud->api->channel == 'stable' ? $this->lang->store->stableChannel : $this->lang->store->testChannel) . ')';
|
||
|
||
$output = "<div class='btn-group header-btn'>";
|
||
if($this->config->cloud->api->switchChannel)
|
||
{
|
||
$stableActive = $this->config->cloud->api->channel == 'stable' ? 'active' : '';
|
||
$testActive = $this->config->cloud->api->channel != 'stable' ? 'active' : '';
|
||
|
||
$output .= "<a href='javascript:;' class='btn' data-toggle='dropdown'>{$title}<span class='caret' style='margin-bottom: -1px;margin-left:5px;'></span></a>";
|
||
$output .= "<ul class='dropdown-menu'>";
|
||
$output .= "<li class='{$stableActive}'>" . html::a(helper::createLink('store', 'browse', 'sortType=update_time&perPage=20&pageID=1&channel=stable'), $this->lang->store->stableChannel) ."</li>";
|
||
$output .= "<li class='{$testActive}'>" . html::a(helper::createLink('store', 'browse', 'sortType=update_time&perPage=20&pageID=1&channel=test'), $this->lang->store->testChannel) ."</li>";
|
||
$output .= "</ul>";
|
||
}
|
||
else
|
||
{
|
||
$output .= "<a href='javascript:;' class='btn' data-toggle='dropdown'>{$title}</a>";
|
||
}
|
||
|
||
$output .= "</div>";
|
||
|
||
return $output;
|
||
}
|
||
|
||
/**
|
||
* Get switcher of app view page of store.
|
||
*
|
||
* @param object $app
|
||
* @access public
|
||
* @return string
|
||
*/
|
||
public function getAppViewSwitcher($app)
|
||
{
|
||
$output = $this->getBrowseSwitcher();
|
||
$output .= "<div class='btn-group header-btn'>";
|
||
$output .= html::a(helper::createLink('store', 'appview', "id=$app->id"), $app->alias, '', 'class="btn"');
|
||
$output .= "</div>";
|
||
|
||
return $output;
|
||
}
|
||
|
||
/**
|
||
* Get app dynamic news from Qucheng offical site.
|
||
*
|
||
* @param object $cloudApp
|
||
* @param int $pageID
|
||
* @param int $recPerPage
|
||
* @access public
|
||
* @return object|null
|
||
*/
|
||
public function appDynamic($cloudApp, $pageID = 1, $recPerPage = 20)
|
||
{
|
||
$alias = strtolower(str_replace('-', '', $cloudApp->chart));
|
||
$url = $this->config->store->quchengSiteHost . "/article-apibrowse-{$alias}-{$pageID}-{$recPerPage}.html";
|
||
|
||
$result = commonModel::apiGet($url);
|
||
if($result && $result->code == 200) return $result->data;
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* Get solution list.
|
||
*
|
||
* @param string $sortBy possible vlues: id,name,create_time,update_time
|
||
* @param string $keyword
|
||
* @param int $page
|
||
* @param int $pageSize
|
||
* @access public
|
||
* @return object
|
||
*/
|
||
public function searchSolutions($sortBy = '', $keyword = '', $page = 1, $pageSize = 20)
|
||
{
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/solution/list?channel='. $this->config->cloud->api->channel;
|
||
$apiUrl .= "&sort=" . rawurlencode(trim($sortBy));
|
||
$apiUrl .= "&q=" . rawurlencode(trim($keyword));
|
||
$apiUrl .= "&page=$page";
|
||
$apiUrl .= "&page_size=$pageSize";
|
||
|
||
$result = commonModel::apiGet($apiUrl, array(), $this->config->cloud->api->headers);
|
||
if($result->code == 200) return $result->data;
|
||
|
||
$pagedApps = new stdclass;
|
||
$pagedApps->apps = array();
|
||
$pagedApps->total = 0;
|
||
return $pagedApps;
|
||
}
|
||
|
||
/**
|
||
* Get solution info.
|
||
*
|
||
* @param string $type
|
||
* @param int|string $value
|
||
* @access public
|
||
* @return object
|
||
*/
|
||
public function getSolution($type, $value)
|
||
{
|
||
$apiParams = array();
|
||
$apiParams[$type] = $value;
|
||
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/solution/info?channel='. $this->config->cloud->api->channel;
|
||
$result = commonModel::apiGet($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||
if(!isset($result->code) || $result->code != 200) return new stdclass();
|
||
|
||
$solution = $result->data;
|
||
$solution->apps = array_combine(helper::arrayColumn($solution->apps, 'chart'), $solution->apps);
|
||
|
||
return $solution;
|
||
}
|
||
/**
|
||
* Get solution config.
|
||
*
|
||
* @param string $type
|
||
* @param int|string $value
|
||
* @access public
|
||
* @return object
|
||
*/
|
||
public function solutionConfig($type, $value)
|
||
{
|
||
$apiParams = array();
|
||
$apiParams[$type] = $value;
|
||
|
||
$apiUrl = $this->config->cloud->api->host;
|
||
$apiUrl .= '/api/market/solution/schema?channel='. $this->config->cloud->api->channel;
|
||
$result = commonModel::apiGet($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||
if(!isset($result->code) || $result->code != 200) return new stdclass();
|
||
|
||
return $result->data;
|
||
}
|
||
}
|