From 298a7cd801810c5da9ead569288561bc604fbb00 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Mon, 28 Apr 2014 15:42:13 +0200 Subject: [PATCH] Plugin-Store integration (work in progress) --- wcfsetup/install/files/acp/js/WCF.ACP.js | 137 +++++++++++++++++- .../templates/pluginStorePurchasedItems.tpl | 74 ++++++++++ wcfsetup/install/files/js/WCF.js | 55 +++++++ .../PluginStorePurchasedItemsPage.class.php | 60 +++++++- .../lib/data/package/PackageAction.class.php | 7 +- wcfsetup/install/lang/de.xml | 27 ++-- 6 files changed, 334 insertions(+), 26 deletions(-) create mode 100644 wcfsetup/install/files/acp/templates/pluginStorePurchasedItems.tpl diff --git a/wcfsetup/install/files/acp/js/WCF.ACP.js b/wcfsetup/install/files/acp/js/WCF.ACP.js index 786ad5df1f..a28a463b3f 100644 --- a/wcfsetup/install/files/acp/js/WCF.ACP.js +++ b/wcfsetup/install/files/acp/js/WCF.ACP.js @@ -1218,6 +1218,130 @@ WCF.ACP.Package.Search = Class.extend({ } }); +WCF.ACP.Package.Server = { + +}; + +WCF.ACP.Package.Server.Installation = Class.extend({ + _proxy: null, + _selectedPackage: '', + + init: function() { + this._dialog = null; + this._selectedPackage = null; + + this._proxy = new WCF.Action.Proxy({ + success: $.proxy(this._success, this) + }); + }, + + bind: function() { + $('.jsButtonPackageInstall').removeClass('jsButtonPackageInstall').click($.proxy(this._click, this)); + }, + + /** + * Prepares a package installation. + * + * @param object event + */ + _click: function(event) { + var $button = $(event.currentTarget); + WCF.System.Confirmation.show($button.data('confirmMessage'), $.proxy(function(action) { + if (action === 'confirm') { + this._selectedPackage = $button.data('package'); + this._selectedPackageVersion = $button.data('packageVersion'); + this._prepareInstallation(); + } + }, this)); + }, + + /** + * Handles successful AJAX requests. + * + * @param object data + */ + _success: function(data) { + if (data.returnValues.queueID) { + if (this._dialog !== null) { + this._dialog.wcfDialog('close'); + } + + var $installation = new WCF.ACP.Package.Installation(data.returnValues.queueID, undefined, false); + $installation.prepareInstallation(); + } + else if (data.returnValues.template) { + if (this._dialog === null) { + this._dialog = $('
' + data.returnValues.template + '
').hide().appendTo(document.body); + this._dialog.wcfDialog({ + title: WCF.Language.get('wcf.acp.package.update.unauthorized') + }); + } + else { + this._dialog.html(data.returnValues.template).wcfDialog('open'); + } + + this._dialog.find('.formSubmit > button').click($.proxy(this._submitAuthentication, this)); + } + }, + + /** + * Submits authentication data for current update server. + * + * @param object event + */ + _submitAuthentication: function(event) { + var $usernameField = $('#packageUpdateServerUsername'); + var $passwordField = $('#packageUpdateServerPassword'); + + // remove error messages if any + $usernameField.next('small.innerError').remove(); + $passwordField.next('small.innerError').remove(); + + var $continue = true; + if ($.trim($usernameField.val()) === '') { + $('' + WCF.Language.get('wcf.global.form.error.empty') + '').insertAfter($usernameField); + $continue = false; + } + + if ($.trim($passwordField.val()) === '') { + $('' + WCF.Language.get('wcf.global.form.error.empty') + '').insertAfter($passwordField); + $continue = false; + } + + if ($continue) { + this._prepareInstallation($(event.currentTarget).data('packageUpdateServerID')); + } + }, + + /** + * Prepares package installation. + * + * @param integer packageUpdateServerID + */ + _prepareInstallation: function(packageUpdateServerID) { + var $parameters = { + 'packages': { } + }; + $parameters['packages'][this._selectedPackage] = this._selectedPackageVersion; + + if (packageUpdateServerID) { + $parameters.authData = { + packageUpdateServerID: packageUpdateServerID, + password: $.trim($('#packageUpdateServerPassword').val()), + saveCredentials: ($('#packageUpdateServerSaveCredentials:checked').length ? true : false), + username: $.trim($('#packageUpdateServerUsername').val()) + }; + } + + this._proxy.setOption('data', { + actionName: 'prepareInstallation', + className: 'wcf\\data\\package\\update\\PackageUpdateAction', + parameters: $parameters + }); + this._proxy.sendRequest(); + }, +}) + /** * Namespace for package update related classes. */ @@ -1504,13 +1628,22 @@ WCF.ACP.PluginStore.PurchasedItems.Search = Class.extend({ this._dialog.wcfDialog('open'); } - this._dialog.find('button').click($.proxy(this._submit, this)); + var $button = this._dialog.find('button').click($.proxy(this._submit, this)); + this._dialog.find('input').keyup(function(event) { + if (event.which == $.ui.keyCode.ENTER) { + $button.trigger('click'); + return false; + } + }); } else if (data.returnValues.noResults) { - this._dialog.wcfDialog('option', 'title', 'Gekaufte Produkte (Plugin-Store)'); + this._dialog.wcfDialog('option', 'title', WCF.Language.get('wcf.acp.pluginstore.purchasedItems')); this._dialog.html(data.returnValues.noResults); this._dialog.wcfDialog('open'); } + else if (data.returnValues.redirectURL) { + window.location = data.returnValues.redirectURL; + } }, _submit: function() { diff --git a/wcfsetup/install/files/acp/templates/pluginStorePurchasedItems.tpl b/wcfsetup/install/files/acp/templates/pluginStorePurchasedItems.tpl new file mode 100644 index 0000000000..b40327331a --- /dev/null +++ b/wcfsetup/install/files/acp/templates/pluginStorePurchasedItems.tpl @@ -0,0 +1,74 @@ +{include file='header' pageTitle='wcf.acp.pluginStore.purchasedItems'} + +
+

{lang}wcf.acp.pluginStore.purchasedItems{/lang}

+
+ +{*
+ +
*} + +{foreach from=$wcfMajorReleases item=wcfMajorRelease} + {if !$productData[$wcfMajorRelease]|empty} + {if !$updateServers[$wcfMajorRelease]|isset} +

{lang}wcf.acp.pluginStore.purchasedItems.updateServer.missing{/lang}

+ {else if $updateServers[$wcfMajorRelease]->isDisabled} +

{lang}wcf.acp.pluginStore.purchasedItems.updateServer.disabled{/lang}

+ {/if} + +
+
+

{lang}wcf.acp.pluginStore.purchasedItems.wcfMajorRelease{/lang} {#$productData[$wcfMajorRelease]|count}

+
+ + + + + + + + + + + + + {foreach from=$productData[$wcfMajorRelease] item=product} + + + + + + + + {/foreach} + +
{lang}wcf.acp.package.name{/lang}{lang}wcf.acp.package.author{/lang}{lang}wcf.acp.package.version{/lang}{lang}wcf.acp.package.installedVersion{/lang}
+ {if $product[status] == 'install'} + + {else if $product[status] == 'update'} + + {else} + + {/if} + {$product[packageName]}{if $product[authorURL]}{$product[author]}{else}{$product[author]}{/if}{$product[version][available]}{if $product[version][installed]}{$product[version][installed]}{else}-{/if}
+
+ {/if} +{/foreach} + +{*
+ +
*} + +{include file='footer'} diff --git a/wcfsetup/install/files/js/WCF.js b/wcfsetup/install/files/js/WCF.js index 735b904b93..8c4adc12a1 100755 --- a/wcfsetup/install/files/js/WCF.js +++ b/wcfsetup/install/files/js/WCF.js @@ -6653,6 +6653,61 @@ WCF.System.Mobile.UX = { } }; +WCF.System.Page.Multiple = Class.extend({ + _cache: { }, + _options: { }, + _pageNo: 1, + _pages: 0, + + init: function(options) { + this._options = $.extend({ + // elements + container: null, + pagination: null, + + // callbacks + loadItems: null + }, options); + }, + + /** + * Callback after page has changed. + * + * @param object event + * @param object data + */ + _showPage: function(event, data) { + if (data && data.activePage) { + if (!data.template) { + this._previousPageNo = this._pageNo; + } + + this._pageNo = data.activePage; + } + + if (this._cache[this._pageNo] || (data && data.template)) { + this._cache[this._previousPageNo] = this._list.children().detach(); + + if (data && data.template) { + this._list.html(data.template); + } + else { + this._list.append(this._cache[this._pageNo]); + } + } + else { + this._loadItems(); + } + }, + + showPage: function(pageNo, template) { + this._showPage(null, { + activePage: pageNo, + template: template + }); + } +}); + /** * System notification overlays. * diff --git a/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php b/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php index d5e1e04f3c..caf89b0ce2 100644 --- a/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php @@ -4,6 +4,9 @@ use wcf\page\AbstractPage; use wcf\system\exception\IllegalLinkException; use wcf\system\WCF; use wcf\system\database\util\PreparedStatementConditionBuilder; +use wcf\data\package\PackageCache; +use wcf\data\package\Package; +use wcf\data\package\update\server\PackageUpdateServerList; /** * Shows a list of purchased plugin store items. @@ -32,6 +35,12 @@ class PluginStorePurchasedItemsPage extends AbstractPage { */ public $products = array(); + public $productData = array(); + + public $updateServers = array(); + + public $wcfMajorReleases = array(); + /** * @see \wcf\page\IPage::readParameters() */ @@ -43,7 +52,10 @@ class PluginStorePurchasedItemsPage extends AbstractPage { throw new IllegalLinkException(); } - die("
".print_r($this->products, true));
+		$this->wcfMajorReleases = WCF::getSession()->getVar('__pluginStoreWcfMajorReleases');
+		if (empty($this->wcfMajorReleases)) {
+			throw new IllegalLinkException();
+		}
 	}
 	
 	/**
@@ -52,13 +64,45 @@ class PluginStorePurchasedItemsPage extends AbstractPage {
 	public function readData() {
 		parent::readData();
 		
-		$availableProducts = array();
-		foreach ($this->products as $products) {
-			$availableProducts = array_merge($availableProducts, array_keys($products));
+		$serverList = new PackageUpdateServerList();
+		$serverList->readObjects();
+		foreach ($serverList as $server) {
+			if (preg_match('~https?://store.woltlab.com/(?P[a-z]+)/~', $server->serverURL, $matches)) {
+				$this->updateServers[$matches['wcfMajorRelease']] = $server;
+			}
 		}
 		
-		$conditions = new PreparedStatementConditionBuilder();
-		$conditions->add("package IN (?)")
+		foreach ($this->products as $packageUpdateID => $product) {
+			$wcfMajorRelease = $product['wcfMajorRelease'];
+			if (!isset($this->productData[$wcfMajorRelease])) {
+				$this->productData[$wcfMajorRelease] = array();
+			}
+			
+			$languageCode = WCF::getLanguage()->languageCode;
+			$packageName = (isset($product['packageName'][$languageCode])) ? $product['packageName'][$languageCode] : $product['packageName']['en'];
+			
+			$this->productData[$wcfMajorRelease][$packageUpdateID] = array(
+				'author' => $product['author'],
+				'authorURL' => $product['authorURL'],
+				'package'  => $product['package'],
+				'packageName' => $packageName,
+				'pluginStoreURL' => $product['pluginStoreURL'],
+				'version' => array(
+					'available' => $product['lastVersion'],
+					'installed' => ''
+				),
+				'status' => (isset($this->updateServers[$wcfMajorRelease]) ? 'install' : 'unavailable')
+			);
+			
+			$package = PackageCache::getInstance()->getPackageByIdentifier($product['package']);
+			if ($package !== null) {
+				$this->productData[$wcfMajorRelease][$packageUpdateID]['version']['installed'] = $package->packageVersion;
+				
+				if (Package::compareVersion($product['lastVersion'], $package->packageVersion, '>')) {
+					$this->productData[$wcfMajorRelease][$packageUpdateID]['status'] = 'update';
+				}
+			}
+		}
 	}
 	
 	/**
@@ -68,7 +112,9 @@ class PluginStorePurchasedItemsPage extends AbstractPage {
 		parent::assignVariables();
 		
 		WCF::getTPL()->assign(array(
-			'products' => $this->products
+			'productData' => $this->productData,
+			'updateServers' => $this->updateServers,
+			'wcfMajorReleases' => $this->wcfMajorReleases
 		));
 	}
 }
diff --git a/wcfsetup/install/files/lib/data/package/PackageAction.class.php b/wcfsetup/install/files/lib/data/package/PackageAction.class.php
index 3e7f30c586..58caca33c7 100644
--- a/wcfsetup/install/files/lib/data/package/PackageAction.class.php
+++ b/wcfsetup/install/files/lib/data/package/PackageAction.class.php
@@ -46,10 +46,6 @@ class PackageAction extends AbstractDatabaseObjectAction {
 		$this->readString('password', true);
 		$this->readString('username', true);
 		
-		if (empty($this->parameters['wcfMajorReleases']) || !is_array($this->parameters['wcfMajorReleases'])) {
-			throw new UserInputException('wcfMajorReleases');
-		}
-		
 		if (empty($this->parameters['username'])) {
 			// check if user has already provided credentials
 			$sql = "SELECT	loginUsername, loginPassword
@@ -77,7 +73,7 @@ class PackageAction extends AbstractDatabaseObjectAction {
 		), array(
 			'username' => $this->parameters['username'],
 			'password' => $this->parameters['password'],
-			'wcfMajorReleases' => $this->parameters['wcfMajorReleases']
+			'wcfVersion' => WCF_VERSION
 		));
 		
 		$request->execute();
@@ -94,6 +90,7 @@ class PackageAction extends AbstractDatabaseObjectAction {
 				}
 				else {
 					WCF::getSession()->register('__pluginStoreProducts', $response['products']);
+					WCF::getSession()->register('__pluginStoreWcfMajorReleases', $response['wcfMajorReleases']);
 					
 					return array(
 						'redirectURL' => LinkHandler::getInstance()->getLink('PluginStorePurchasedItems')
diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml
index a206f92175..3e3f1fb53d 100644
--- a/wcfsetup/install/lang/de.xml
+++ b/wcfsetup/install/lang/de.xml
@@ -1031,18 +1031,21 @@ GmbH=Gesellschaft mit beschränkter Haftung]]>
 		
 	
 	
-	
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
-		
+	
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		
+		hinzufügen.
Die Adresse des Servers lautet: „http://store.woltlab.com/{$wcfMajorRelease}/“]]>
+
-- 2.20.1