Source of file MarketItem.php
Size: 19,307 Bytes - Last Modified: 2020-10-24T02:46:31+00:00
/home/travis/build/NextDom/nextdom-core/src/Market/MarketItem.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 | <?php /* This file is part of Jeedom. * * Jeedom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jeedom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jeedom. If not, see <http://www.gnu.org/licenses/>. */ /* This file is part of NextDom Software. * * NextDom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NextDom Software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NextDom Software. If not, see <http://www.gnu.org/licenses/>. */ namespace NextDom\Market; use NextDom\Helpers\DataStorage; use NextDom\Managers\UpdateManager; /** * Class MarketItem * @package NextDom\Market */ class MarketItem { /** * @var int Refresh time of a deposit */ private $REFRESH_TIME_LIMIT = 86400; /** * @var string Plugin ID */ private $id; /** * @var string Plugin name on GitHub */ private $gitName; /** * @var string User GitHub */ private $gitId; /** * @var string Full name of his deposit */ private $fullName; /** * @var string Description */ private $description; /** * @var string URL Git */ private $url; /** * @var string Name of plugin */ private $name; /** * @var string Plugin author */ private $author; /** * @var string Plugin category */ private $category; /** * @var DataStorage Database Manager */ private $dataStorage; /** * @var string Icon path */ private $iconPath; /** * @var string Default branch */ private $defaultBranch; /** * @var array List of branches */ private $branchesList; /** * @var string Licence */ private $licence; /** * @var string Link to the documentation */ private $documentationLink; /** * @var string Link to the changelog */ private $changelogLink; /** * @var string Name of the source */ private $sourceName; /** * @var array Jeedom data on the plugin */ private $updateData; /** * @var array Captures list */ private $screenshots; /** * Builder initializing basic information * * @param string $sourceName Name of the source of the element */ public function __construct($sourceName) { $this->dataStorage = new DataStorage('market'); // @TODO: A supprimer if (!$this->dataStorage->isDataTableExists()) { $this->dataStorage->createDataTable(); } $this->sourceName = $sourceName; $this->iconPath = false; } /** * Create an element from the data of a GitHub repository * * @param string $sourceName Create an element from the data of a GitHub repository * @param string[] $repositoryInformations Deposit Information * * @return MarketItem Element created */ public static function createFromGit(string $sourceName, $repositoryInformations) { $result = new self($sourceName); $result->initWithGlobalInformations($repositoryInformations); return $result; } /** * Lire les informations obtenus par GitHub * * @param string[] $repositoryInformations Informations de GitHub */ public function initWithGlobalInformations($repositoryInformations) { if (array_key_exists('name', $repositoryInformations)) $this->gitName = $repositoryInformations['name']; if (array_key_exists('full_name', $repositoryInformations)) $this->fullName = $repositoryInformations['full_name']; if (array_key_exists('html_url', $repositoryInformations)) $this->url = $repositoryInformations['html_url']; if (array_key_exists('git_id', $repositoryInformations)) $this->gitId = $repositoryInformations['git_id']; if (array_key_exists('description', $repositoryInformations)) $this->description = $repositoryInformations['description']; if (array_key_exists('default_branch', $repositoryInformations)) $this->defaultBranch = $repositoryInformations['default_branch']; } /** * Create an item from the cache * * @param string $sourceName Name of the source * @param string $fullName Full Name * * @return MarketItem Element created */ public static function createFromCache(string $sourceName, string $fullName) { $result = (new self($sourceName)) ->setFullName($fullName); $result->readCache(); return $result; } /** * Read the cache file * * @return bool True if the reading was successful */ public function readCache(): bool { $name = sprintf("repo_data_%s", str_replace("/", "_", $this->fullName)); $json = $this->dataStorage->getJsonData($name); $attrs = ["name", "gitName", "gitId", "fullName", "description", "url", "id", "author", "category", "iconPath", "defaultBranch", "branchesList", "licence", "changelogLink", "documentationLink", "screenshots"]; if ($json === null) { return false; } foreach ($attrs as $c_attr) { if (true === array_key_exists($c_attr, $json)) { $this->$c_attr = $json[$c_attr]; } } if (false !== $this->iconPath) { $path = sprintf("%s/%s", NEXTDOM_ROOT, $this->iconPath); if (false === file_exists($path)) { $this->iconPath = false; } } return true; } /** * Create an element from data in a JSON * * @param string $sourceName Name of the source * @param string[] $jsonData Element data * * @return MarketItem Elément créé */ public static function createFromJson(string $sourceName, $jsonData) { $result = new self($sourceName); $result->initWithJsonInformations($jsonData); return $result; } /** * @param $jsonInformations */ public function initWithJsonInformations($jsonInformations) { if (array_key_exists('id', $jsonInformations)) $this->id = $jsonInformations['id']; if (array_key_exists('repository', $jsonInformations)) $this->gitName = $jsonInformations['repository']; if (array_key_exists('gitId', $jsonInformations)) { $this->gitId = $jsonInformations['gitId']; $this->fullName = $this->gitId . '/' . $this->gitName; $this->url = 'https://github.com/' . $this->gitId . '/' . $this->fullName; } if (array_key_exists('name', $jsonInformations)) $this->name = $jsonInformations['name']; if (array_key_exists('licence', $jsonInformations)) $this->licence = $jsonInformations['licence']; if (array_key_exists('category', $jsonInformations)) $this->category = $jsonInformations['category']; if (array_key_exists('documentation', $jsonInformations)) $this->documentationLink = $jsonInformations['documentation']; if (array_key_exists('changelog', $jsonInformations)) $this->changelogLink = $jsonInformations['changelog']; if (array_key_exists('author', $jsonInformations)) $this->author = $jsonInformations['author']; if (array_key_exists('description', $jsonInformations)) $this->description = $jsonInformations['description']; if (array_key_exists('defaultBranch', $jsonInformations)) $this->defaultBranch = $jsonInformations['defaultBranch']; if (array_key_exists('branches', $jsonInformations)) $this->branchesList = $jsonInformations['branches']; if (array_key_exists('screenshots', $jsonInformations)) $this->screenshots = $jsonInformations['screenshots']; } /** * Test if an update is needed * * @param array $repositoryInformations Informations from GitHub * * @return bool True if an update is needed */ public function isNeedUpdate(array $repositoryInformations): bool { $result = true; $lastUpdate = $this->dataStorage->getRawData('repo_last_update_' . str_replace('/', '_', $repositoryInformations['full_name'])); if ($lastUpdate !== null) { if (time() - $lastUpdate < $this->REFRESH_TIME_LIMIT) { $result = false; } } return $result; } /** * Updates the data of the element * * @return bool True if the update was done. * @throws \Exception */ public function refresh(): bool { $result = false; $infoJsonUrl = 'https://raw.githubusercontent.com/' . $this->fullName . '/' . $this->defaultBranch . '/plugin_info/info.json'; $infoJson = DownloadManager::downloadContent($infoJsonUrl); if (strpos($infoJson, '404: Not Found') === false) { $pluginData = json_decode($infoJson, true); if (is_array($pluginData) && array_key_exists('id', $pluginData)) { $this->addPluginInformations($pluginData); $this->downloadIcon(); $this->branchesList = []; $this->writeCache(); $result = true; } } return $result; } /** * Add the information contained in the plugin's info.json file * * @param string[] $pluginInfo Contenu du fichier info.json */ public function addPluginInformations($pluginInfo) { if (array_key_exists('id', $pluginInfo)) $this->id = $pluginInfo['id']; if (array_key_exists('name', $pluginInfo)) $this->name = $pluginInfo['name']; if (array_key_exists('author', $pluginInfo)) $this->author = $pluginInfo['author']; if (array_key_exists('category', $pluginInfo)) $this->category = $pluginInfo['category']; if (array_key_exists('licence', $pluginInfo)) $this->licence = $pluginInfo['licence']; if (array_key_exists('changelog', $pluginInfo)) $this->changelogLink = $pluginInfo['changelog']; if (array_key_exists('documentation', $pluginInfo)) $this->documentationLink = $pluginInfo['documentation']; if (array_key_exists('description', $pluginInfo) && $pluginInfo['description'] !== null && $pluginInfo['description'] !== '') { $this->description = $pluginInfo['description']; } } /** * Download the plugin icon */ public function downloadIcon() { $iconFilename = str_replace('/', '_', $this->fullName) . '.png'; $iconUrl = 'https://raw.githubusercontent.com/' . $this->fullName . '/' . $this->defaultBranch . '/plugin_info/' . $this->id . '_icon.png'; $targetPath = NEXTDOM_DATA . '/public/img/market_cache/' . $iconFilename; DownloadManager::downloadBinary($iconUrl, $targetPath); if (filesize($targetPath) < 100) { unlink($targetPath); $this->iconPath = '/public/img/unknown_icon.png'; } else { $this->iconPath = '/var/public/img/market_cache/' . $iconFilename; } $this->writeCache(); } /** * Write the cache file in JSON format */ public function writeCache() { $dataArray = $this->getDataInArray(); unset($dataArray['installed']); unset($dataArray['installedBranchData']); $this->dataStorage->storeJsonData('repo_data_' . str_replace('/', '_', $this->fullName), $dataArray); $this->dataStorage->storeRawData('repo_last_update_' . str_replace('/', '_', $this->fullName), time()); } /** * Get all the information in an associative array * * @return array Data array */ public function getDataInArray() { $dataArray = []; $dataArray['name'] = $this->name; $dataArray['gitName'] = $this->gitName; $dataArray['gitId'] = $this->gitId; $dataArray['fullName'] = $this->fullName; $dataArray['description'] = $this->description; $dataArray['url'] = $this->url; $dataArray['id'] = $this->id; $dataArray['author'] = $this->author; $dataArray['category'] = $this->category; $dataArray['iconPath'] = $this->iconPath; $dataArray['defaultBranch'] = $this->defaultBranch; $dataArray['branchesList'] = $this->branchesList; $dataArray['licence'] = $this->licence; $dataArray['sourceName'] = $this->sourceName; $dataArray['changelogLink'] = $this->changelogLink; $dataArray['documentationLink'] = $this->documentationLink; $dataArray['screenshots'] = $this->screenshots; $this->initUpdateData(); $dataArray['installed'] = $this->isInstalled(); $dataArray['installedBranchData'] = false; if ($dataArray['installed']) { $dataArray['installedBranchData'] = $this->getInstalledBranchData(); } return $dataArray; } /** * Initialize the Jeedom data on the plugin */ private function initUpdateData() { $this->updateData = UpdateManager::byLogicalId($this->id); } /** * Test if the plugin is installed * * @return bool True if the plugin is installed */ public function isInstalled(): bool { $result = false; if ($this->updateData !== false) { $result = true; } return $result; } /** * @return array|bool */ private function getInstalledBranchData() { $result = false; if ($this->updateData !== false && $this->updateData !== null) { $configuration = $this->updateData->getConfiguration(); if (is_array($configuration) && array_key_exists('version', $configuration)) { $result = []; $result['branch'] = $configuration['version']; $result['hash'] = $this->updateData->getLocalVersion(); $result['needUpdate'] = false; $result['id'] = $this->updateData->getId(); if ($this->updateData->getSource() === 'github') { if ($this->updateData->getStatus() === 'update') { $result['needUpdate'] = true; } else { foreach ($this->branchesList as $branch) { if ($branch['name'] === $result['branch'] && $branch['hash'] !== $result['hash']) { $result['needUpdate'] = true; } } } } } } return $result; } /** * Update branch data * * @return bool True if the data was found * @throws \Exception */ public function downloadBranchesInformations(): bool { $result = false; $baseGitRepoUrl = 'https://api.github.com/repos/' . $this->fullName . '/branches'; $branches = DownloadManager::downloadContent($baseGitRepoUrl); if ($branches !== false) { $branches = json_decode($branches, true); $this->branchesList = []; foreach ($branches as $branch) { if (is_array($branch) && array_key_exists('name', $branch)) { $branchData = []; $branchData['name'] = $branch['name']; $branchData['hash'] = $branch['commit']['sha']; array_push($this->branchesList, $branchData); } } $result = true; } return $result; } public function updateBranchDataFromInstalled() { $this->initUpdateData(); $installedBranch = $this->getInstalledBranchData(); $added = false; for ($branchIndex = 0; $branchIndex < count($this->branchesList); ++$branchIndex) { if ($this->branchesList[$branchIndex]['name'] == $installedBranch['branch']) { $this->branchesList[$branchIndex]['hash'] = $installedBranch['hash']; $added = true; } } if ($added === false) { $branch = []; $branch['name'] = $installedBranch['branch']; $branch['hash'] = $installedBranch['hash']; array_push($this->branchesList, $branch); } $this->writeCache(); } /** * Get the name of the depot. * * @return string name of the depot */ public function getGitName() { return $this->gitName; } /** * Get the full name * * @return string full name */ public function getFullName() { return $this->fullName; } /** * Define the name of the deposit full * * @param string $fullName full name * * @return MarketItem Instance of the object */ public function setFullName($fullName): MarketItem { $this->fullName = $fullName; return $this; } /** * Obtenir la description du dépot * * @return string Description */ public function getDescription() { return $this->description; } /** * Obtenir le lien * * @return string Lien */ public function getUrl() { return $this->url; } /** * Obtenir l'identifiant * * @return string Identifiant */ public function getId() { return $this->id; } /** * Obtenir l'auteur * * @return string Auteur */ public function getAuthor() { return $this->author; } /** * Obtenir la catégorie * * @return string Catégorie */ public function getCategory() { return $this->category; } /** * Obtenir le nom * * @return string Nom */ public function getName() { return $this->name; } /** * Obtenir l'utilisateur GitHub * * @return string Utilisateur GitHub */ public function getGitId() { return $this->gitId; } /** * Get the list of branches of the plugin * * @return array List of branches */ public function getBranchesList() { return $this->branchesList; } /** * @return string */ public function getIconPath() { return $this->iconPath; } } |