From: Alexander Ebert Date: Sat, 26 Apr 2014 21:14:31 +0000 (+0200) Subject: Added integration of purchased Plugin-Store products X-Git-Tag: 2.1.0_Alpha_1~867 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=317c8af562c1ab6d41add3ed3079b267810d19d3;p=GitHub%2FWoltLab%2FWCF.git Added integration of purchased Plugin-Store products --- diff --git a/wcfsetup/install/files/acp/js/WCF.ACP.js b/wcfsetup/install/files/acp/js/WCF.ACP.js index b104a9b4ed..786ad5df1f 100644 --- a/wcfsetup/install/files/acp/js/WCF.ACP.js +++ b/wcfsetup/install/files/acp/js/WCF.ACP.js @@ -1447,6 +1447,88 @@ WCF.ACP.Package.Update.Search = Class.extend({ } }); +/** + * Namespace for classes related to the WoltLab Plugin-Store. + */ +WCF.ACP.PluginStore = { }; + +/** + * Namespace for classes handling items purchased in the WoltLab Plugin-Store. + */ +WCF.ACP.PluginStore.PurchasedItems = { }; + +/** + * Searches for purchased items available for install but not yet installed. + */ +WCF.ACP.PluginStore.PurchasedItems.Search = Class.extend({ + _dialog: null, + _proxy: null, + _wcfMajorReleases: [ ], + + init: function(wcfMajorReleases) { + this._dialog = null; + this._proxy = new WCF.Action.Proxy({ + success: $.proxy(this._success, this) + }); + this._wcfMajorReleases = wcfMajorReleases; + if (!this._wcfMajorReleases.length) { + console.debug("[WCF.ACP.PluginStore.PurchasedItems.Search] No suitable WCF major releases found, aborting."); + return; + } + + var $button = $('
  • ' + WCF.Language.get('wcf.acp.pluginstore.purchasedItems.button.search') + '
  • '); + $button.prependTo($('.contentNavigation:eq(0) > nav > ul')).click($.proxy(this._click, this)); + }, + + _click: function() { + this._proxy.setOption('data', { + actionName: 'searchForPurchasedItems', + className: 'wcf\\data\\package\\PackageAction', + parameters: { + wcfMajorReleases: this._wcfMajorReleases + } + }); + this._proxy.sendRequest(); + }, + + _success: function(data, textStatus, jqXHR) { + if (data.returnValues.template) { + if (this._dialog === null) { + this._dialog = $('
    ').hide().appendTo(document.body); + this._dialog.html(data.returnValues.template).wcfDialog({ + title: WCF.Language.get('wcf.acp.pluginstore.authorization') + }); + } + else { + this._dialog.html(data.returnValues.template); + this._dialog.wcfDialog('open'); + } + + this._dialog.find('button').click($.proxy(this._submit, this)); + } + else if (data.returnValues.noResults) { + this._dialog.wcfDialog('option', 'title', 'Gekaufte Produkte (Plugin-Store)'); + this._dialog.html(data.returnValues.noResults); + this._dialog.wcfDialog('open'); + } + }, + + _submit: function() { + this._dialog.wcfDialog('close'); + + this._proxy.setOption('data', { + actionName: 'searchForPurchasedItems', + className: 'wcf\\data\\package\\PackageAction', + parameters: { + password: $('#pluginStorePassword').val(), + username: $('#pluginStoreUsername').val(), + wcfMajorReleases: this._wcfMajorReleases + } + }); + this._proxy.sendRequest(); + } +}); + /** * Handles option selection. */ diff --git a/wcfsetup/install/files/acp/templates/packageList.tpl b/wcfsetup/install/files/acp/templates/packageList.tpl index e60cc04591..5d1b26df23 100644 --- a/wcfsetup/install/files/acp/templates/packageList.tpl +++ b/wcfsetup/install/files/acp/templates/packageList.tpl @@ -6,7 +6,11 @@ WCF.Language.addObject({ 'wcf.acp.package.searchForUpdates': '{lang}wcf.acp.package.searchForUpdates{/lang}', 'wcf.acp.package.searchForUpdates.noResults': '{lang}wcf.acp.package.searchForUpdates.noResults{/lang}', - 'wcf.acp.package.uninstallation.title': '{lang}wcf.acp.package.uninstallation.title{/lang}' + 'wcf.acp.package.uninstallation.title': '{lang}wcf.acp.package.uninstallation.title{/lang}', + 'wcf.acp.pluginstore.authorization': '{lang}wcf.acp.pluginstore.authorization{/lang}', + 'wcf.acp.pluginstore.purchasedItems': '{lang}wcf.acp.pluginstore.purchasedItems{/lang}', + 'wcf.acp.pluginstore.purchasedItems.button.search': '{lang}wcf.acp.pluginstore.purchasedItems.button.search{/lang}', + 'wcf.acp.pluginstore.purchasedItems.noResults': '{lang}wcf.acp.pluginstore.purchasedItems.noResults{/lang}' }); {if $__wcf->session->getPermission('admin.system.package.canUninstallPackage')} @@ -22,6 +26,8 @@ {if $__wcf->session->getPermission('admin.system.package.canUpdatePackage')} new WCF.ACP.Package.Update.Search(); {/if} + + new WCF.ACP.PluginStore.PurchasedItems.Search([ {implode from=$wcfMajorReleases item=wcfMajorRelease}'{$wcfMajorRelease}'{/implode} ]); }); //]]> diff --git a/wcfsetup/install/files/acp/templates/pluginStoreAuthorization.tpl b/wcfsetup/install/files/acp/templates/pluginStoreAuthorization.tpl new file mode 100644 index 0000000000..7c951745f8 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/pluginStoreAuthorization.tpl @@ -0,0 +1,22 @@ +{if $rejected} +

    {lang}wcf.acp.pluginstore.authorization.credentails.rejected{/lang}

    +{/if} + + + {lang}wcf.acp.pluginstore.authorization.credentials{/lang} + {lang}wcf.acp.pluginstore.authorization.credentails.description{/lang} + +
    +
    +
    +
    + +
    +
    +
    +
    + + +
    + +
    \ No newline at end of file diff --git a/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php b/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php index 14c9232aeb..a0bc1fbdb0 100644 --- a/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php +++ b/wcfsetup/install/files/lib/acp/page/PackageListPage.class.php @@ -2,6 +2,7 @@ namespace wcf\acp\page; use wcf\page\SortablePage; use wcf\system\WCF; +use wcf\data\package\update\server\PackageUpdateServer; /** * Shows a list of all installed packages. @@ -55,6 +56,12 @@ class PackageListPage extends SortablePage { */ public $objectListClassName = 'wcf\data\package\PackageList'; + /** + * list of WCF major releases covered by existing store update servers + * @var array + */ + public $wcfMajorReleases = array(); + /** * @see \wcf\page\IPage::readParameters() */ @@ -64,6 +71,20 @@ class PackageListPage extends SortablePage { if (isset($_GET['packageID'])) $this->packageID = intval($_GET['packageID']); } + /** + * @see \wcf\page\IPage::readData() + */ + public function readData() { + parent::readData(); + + $updateServers = PackageUpdateServer::getActiveUpdateServers(); + foreach ($updateServers as $updateServer) { + if (preg_match('~^https?://store.woltlab.com/(maelstrom|typhoon)/$~', $updateServer->serverURL, $matches)) { + $this->wcfMajorReleases[] = $matches[1]; + } + } + } + /** * @see \wcf\page\IPage::assignVariables() */ @@ -71,7 +92,8 @@ class PackageListPage extends SortablePage { parent::assignVariables(); WCF::getTPL()->assign(array( - 'packageID' => $this->packageID + 'packageID' => $this->packageID, + 'wcfMajorReleases' => $this->wcfMajorReleases )); } diff --git a/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php b/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php new file mode 100644 index 0000000000..d5e1e04f3c --- /dev/null +++ b/wcfsetup/install/files/lib/acp/page/PluginStorePurchasedItemsPage.class.php @@ -0,0 +1,74 @@ + + * @package com.woltlab.wcf + * @subpackage acp.page + * @category Community Framework + */ +class PluginStorePurchasedItemsPage extends AbstractPage { + /** + * @see \wcf\page\AbstractPage::$activeMenuItem + */ + public $activeMenuItem = 'wcf.acp.menu.link.package'; + + /** + * @see \wcf\page\AbstractPage::$neededPermissions + */ + public $neededPermissions = array('admin.system.package.canUpdatePackage', 'admin.system.package.canUninstallPackage'); + + /** + * list of purchased products grouped by WCF major release. + * @var array + */ + public $products = array(); + + /** + * @see \wcf\page\IPage::readParameters() + */ + public function readParameters() { + parent::readParameters(); + + $this->products = WCF::getSession()->getVar('__pluginStoreProducts'); + if (empty($this->products)) { + throw new IllegalLinkException(); + } + + die("
    ".print_r($this->products, true));
    +	}
    +	
    +	/**
    +	 * @see	\wcf\page\IPage::readData()
    +	 */
    +	public function readData() {
    +		parent::readData();
    +		
    +		$availableProducts = array();
    +		foreach ($this->products as $products) {
    +			$availableProducts = array_merge($availableProducts, array_keys($products));
    +		}
    +		
    +		$conditions = new PreparedStatementConditionBuilder();
    +		$conditions->add("package IN (?)")
    +	}
    +	
    +	/**
    +	 * @see	\wcf\page\IPage::assignVariables()
    +	 */
    +	public function assignVariables() {
    +		parent::assignVariables();
    +		
    +		WCF::getTPL()->assign(array(
    +			'products' => $this->products
    +		));
    +	}
    +}
    diff --git a/wcfsetup/install/files/lib/data/package/PackageAction.class.php b/wcfsetup/install/files/lib/data/package/PackageAction.class.php
    index e03a5be583..3e7f30c586 100644
    --- a/wcfsetup/install/files/lib/data/package/PackageAction.class.php
    +++ b/wcfsetup/install/files/lib/data/package/PackageAction.class.php
    @@ -1,6 +1,13 @@
     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
    +				FROM	wcf".WCF_N."_package_update_server
    +				WHERE	serverURL = ?";
    +			$statement = WCF::getDB()->prepareStatement($sql, 1);
    +			$statement->execute(array('http://store.woltlab.com/typhoon/'));
    +			$row = $statement->fetchArray();
    +			if (!empty($row['loginUsername']) && !empty($row['loginPassword'])) {
    +				$this->parameters['password'] = $row['loginPassword'];
    +				$this->parameters['username'] = $row['loginUsername'];
    +			}
    +		}
    +	}
    +	
    +	public function searchForPurchasedItems() {
    +		if (empty($this->parameters['username']) || empty($this->parameters['password'])) {
    +			return array(
    +				'template' => $this->renderAuthorizationDialog(false)
    +			);
    +		}
    +		
    +		$request = new HTTPRequest('https://www.woltlab.com/api/1.0/customer/purchases/list.json', array(
    +			'method' => 'POST'
    +		), array(
    +			'username' => $this->parameters['username'],
    +			'password' => $this->parameters['password'],
    +			'wcfMajorReleases' => $this->parameters['wcfMajorReleases']
    +		));
    +		
    +		$request->execute();
    +		$reply = $request->getReply();
    +		$response = JSON::decode($reply['body']);
    +		
    +		$code = (isset($response['status'])) ? $response['status'] : 500;
    +		switch ($code) {
    +			case 200:
    +				if (empty($response['products'])) {
    +					return array(
    +						'noResults' => WCF::getLanguage()->get('wcf.acp.pluginstore.purchasedItems.noResults')
    +					);
    +				}
    +				else {
    +					WCF::getSession()->register('__pluginStoreProducts', $response['products']);
    +					
    +					return array(
    +						'redirectURL' => LinkHandler::getInstance()->getLink('PluginStorePurchasedItems')
    +					);
    +				}
    +			break;
    +			
    +			// authentication error
    +			case 401:
    +				return array(
    +					'template' => $this->renderAuthorizationDialog(true)
    +				);
    +			break;
    +			
    +			// any other kind of errors
    +			default:
    +				throw new SystemException(WCF::getLanguage()->getDynamicVariable('wcf.acp.pluginstore.api.error', array('status' => $code)));
    +			break;
    +		}
    +	}
    +	
    +	protected function renderAuthorizationDialog($rejected) {
    +		WCF::getTPL()->assign(array(
    +			'rejected' => $rejected
    +		));
    +		
    +		return WCF::getTPL()->fetch('pluginStoreAuthorization');
    +	}
     }
    diff --git a/wcfsetup/install/files/lib/util/JSON.class.php b/wcfsetup/install/files/lib/util/JSON.class.php
    index a880aa20e0..444d8ca0e8 100644
    --- a/wcfsetup/install/files/lib/util/JSON.class.php
    +++ b/wcfsetup/install/files/lib/util/JSON.class.php
    @@ -35,7 +35,7 @@ final class JSON {
     		$data = json_decode($json, $asArray);
     		
     		if ($data === null && self::getLastError() !== JSON_ERROR_NONE) {
    -			throw new SystemException('Could not decode JSON "'.$json.'"');
    +			throw new SystemException('Could not decode JSON (error '.self::getLastError().'): '.$json);
     		}
     		
     		return $data;
    diff --git a/wcfsetup/install/lang/de.xml b/wcfsetup/install/lang/de.xml
    index f1f5028e20..a206f92175 100644
    --- a/wcfsetup/install/lang/de.xml
    +++ b/wcfsetup/install/lang/de.xml
    @@ -1031,6 +1031,20 @@ GmbH=Gesellschaft mit beschränkter Haftung]]>
     		
     	
     	
    +	
    +		
    +		
    +		
    +		
    +		
    +		
    +		
    +		
    +		
    +		
    +		
    +	
    +