Added ability to install packages through search
authorAlexander Ebert <ebert@woltlab.com>
Fri, 3 May 2013 14:39:08 +0000 (16:39 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 3 May 2013 14:39:08 +0000 (16:39 +0200)
wcfsetup/install/files/acp/js/WCF.ACP.js
wcfsetup/install/files/acp/templates/header.tpl
wcfsetup/install/files/acp/templates/packageSearchResultList.tpl
wcfsetup/install/files/acp/templates/packageStartInstall.tpl
wcfsetup/install/files/lib/data/package/update/PackageUpdateAction.class.php

index 81d70fade3069ec4877bd292f54615a065f49d93..3e686ff6f70f814a815058bac5eacc33418258b8 100644 (file)
@@ -746,6 +746,12 @@ WCF.ACP.Package.Search = Class.extend({
         */
        _container: null,
        
+       /**
+        * dialog overlay
+        * @var jQuery
+        */
+       _dialog: null,
+       
        /**
         * package input field
         * @var jQuery
@@ -800,6 +806,17 @@ WCF.ACP.Package.Search = Class.extend({
         */
        _searchID: 0,
        
+       /**
+        * currently selected package
+        * @var string
+        */
+       _selectedPackage: '',
+       
+       /**
+        * currently selected package's version
+        */
+       _selectedPackageVersion: '',
+       
        /**
         * Initializes the WCF.ACP.Package.Seach class.
         */
@@ -807,6 +824,7 @@ WCF.ACP.Package.Search = Class.extend({
                this._button = null;
                this._cache = { };
                this._container = $('#packageSearch');
+               this._dialog = null;
                this._package = null;
                this._packageName = null;
                this._packageSearchResultContainer = $('#packageSearchResultContainer');
@@ -815,6 +833,8 @@ WCF.ACP.Package.Search = Class.extend({
                this._pageNo = 1;
                this._searchDescription = null;
                this._searchID = 0;
+               this._selectedPackage = '';
+               this._selectedPackageVersion = '';
                
                this._proxy = new WCF.Action.Proxy({
                        success: $.proxy(this._success, this)
@@ -909,6 +929,30 @@ WCF.ACP.Package.Search = Class.extend({
                                this._insertTemplate(data.returnValues.template);
                        break;
                        
+                       case 'prepareInstallation':
+                               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 = $('<div>' + data.returnValues.template + '</div>').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));
+                               }
+                       break;
+                       
                        case 'search':
                                this._pageCount = data.returnValues.pageCount;
                                this._searchID = data.returnValues.searchID;
@@ -919,6 +963,35 @@ WCF.ACP.Package.Search = Class.extend({
                }
        },
        
+       /**
+        * 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()) === '') {
+                       $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($usernameField);
+                       $continue = false;
+               }
+               
+               if ($.trim($passwordField.val()) === '') {
+                       $('<small class="innerError">' + WCF.Language.get('wcf.global.form.error.empty') + '</small>').insertAfter($passwordField);
+                       $continue = false;
+               }
+               
+               if ($continue) {
+                       this._prepareInstallation($(event.currentTarget).data('packageUpdateServerID'));
+               }
+       },
+       
        /**
         * Inserts search result list template.
         * 
@@ -936,8 +1009,55 @@ WCF.ACP.Package.Search = Class.extend({
                // update badge count
                if (count !== undefined) {
                        this._content = { 1: template };
-                       this._packageSearchResultContainer.find('> header > h1 > .badge').html(count);
+                       this._packageSearchResultContainer.find('> header > h2 > .badge').html(count);
                }
+               
+               // bind listener
+               this._packageSearchResultList.find('.jsInstallPackage').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));
+       },
+       
+       /**
+        * Prepares package installation.
+        * 
+        * @param       integer         packageUpdateServerID
+        */
+       _prepareInstallation: function(packageUpdateServerID) {
+               var $parameters = {
+                       'package': { }
+               };
+               $parameters['package'][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();
        },
        
        /**
@@ -949,12 +1069,12 @@ WCF.ACP.Package.Search = Class.extend({
                this._packageSearchResultContainer.find('.pageNavigation').wcfPages('destroy').remove();
                
                if (this._pageCount > 1) {
-                       var $topNavigation = $('<div class="contentNavigation" />').insertBefore(this._packageSearchResultList).wcfPages({
+                       $('<div class="contentNavigation" />').insertBefore(this._packageSearchResultList).wcfPages({
                                activePage: this._pageNo,
                                maxPage: this._pageCount
                        }).bind('wcfpagesswitched', $.proxy(this._showPage, this));
                        
-                       var $bottomNavigation = $('<div class="contentNavigation" />').insertAfter(this._packageSearchResultList).wcfPages({
+                       $('<div class="contentNavigation" />').insertAfter(this._packageSearchResultList).wcfPages({
                                activePage: this._pageNo,
                                maxPage: this._pageCount
                        }).bind('wcfpagesswitched', $.proxy(this._showPage, this));
@@ -1093,7 +1213,7 @@ WCF.ACP.Package.Update.Manager = Class.extend({
                                        password: $.trim($('#packageUpdateServerPassword').val()),
                                        saveCredentials: ($('#packageUpdateServerSaveCredentials:checked').length ? true : false),
                                        username: $.trim($('#packageUpdateServerUsername').val())
-                               }
+                               };
                        }
                        
                        this._proxy.setOption('data', {
index 9ca9398070a24876bda059c32694c5f609db2f19..72caf6461aafa9f916bc8d45c4454ddc70474990 100644 (file)
@@ -75,6 +75,7 @@
                                'wcf.global.decimalPoint': '{capture assign=decimalPoint}{lang}wcf.global.decimalPoint{/lang}{/capture}{$decimalPoint|encodeJS}',
                                'wcf.global.error.timeout': '{lang}wcf.global.error.timeout{/lang}',
                                'wcf.global.error.title': '{lang}wcf.global.error.title{/lang}',
+                               'wcf.global.form.error.empty': '{lang}wcf.global.form.error.empty{/lang}',
                                'wcf.global.loading': '{lang}wcf.global.loading{/lang}',
                                'wcf.global.page.jumpTo': '{lang}wcf.global.page.jumpTo{/lang}',
                                'wcf.global.page.jumpTo.description': '{lang}wcf.global.page.jumpTo.description{/lang}',
index 32ac1bd4b01abd22e4a0f0510d709b3f1c97d633..b726275320cf8f63ce7b8e315f694357521dda6a 100644 (file)
@@ -18,7 +18,7 @@
                                        {foreach from=$packageUpdates item=$package}
                                                <tr class="jsPackageRow">
                                                        <td class="columnIcon">
-                                                               <span class="icon icon16 icon-plus pointer jsTooltip" title="{lang}wcf.acp.package.button.install{/lang}"></span>
+                                                               <a class="jsInstallPackage" data-confirm-message="{lang}wcf.acp.package.install.confirmMessage{/lang}" data-package="{$package->package}" data-package-version="{$package->getAccessibleVersion()->packageVersion}"><span class="icon icon16 icon-plus jsTooltip" title="{lang}wcf.acp.package.button.install{/lang}"></span></a>
                                                                
                                                                {event name='buttons'}
                                                        </td>
index 297531e67e3867d06c153f2d06e8eb6f62a4751f..b893de042042519a30c3fa850143ade8d32bdac2 100644 (file)
@@ -8,6 +8,10 @@
 <script type="text/javascript">
        //<![CDATA[
        $(function() {
+               WCF.Language.addObject({
+                       'wcf.acp.package.update.unauthorized': '{lang}wcf.acp.package.update.unauthorized{/lang}'
+               });
+               
                WCF.TabMenu.init();
                
                new WCF.ACP.Package.Search();
index 9af6d9cbd2e1a9429f290f55d76f5e30bc2e251e..f434172f2d96198a7bdd4d2c4bf880fe65046a73 100644 (file)
@@ -69,10 +69,13 @@ class PackageUpdateAction extends AbstractDatabaseObjectAction {
                if (!empty($this->parameters['packageName'])) {
                        $conditions->add("package_update.packageName LIKE ?", array('%'.$this->parameters['packageName'].'%'));
                }
+               $conditions->add("package.packageID IS NULL");
                
                // find matching packages
                $sql = "SELECT          package_update.packageUpdateID
                        FROM            wcf".WCF_N."_package_update package_update
+                       LEFT JOIN       wcf".WCF_N."_package package
+                       ON              (package.package = package_update.package)
                        ".$conditions."
                        ORDER BY        package_update.packageName ASC";
                $statement = WCF::getDB()->prepareStatement($sql, 1000);
@@ -213,7 +216,7 @@ class PackageUpdateAction extends AbstractDatabaseObjectAction {
                $conditions = new PreparedStatementConditionBuilder();
                $conditions->add("packageUpdateID IN (?)", array(array_keys($updateData)));
                
-               $sql = "SELECT  packageUpdateID, packageName, packageDescription, author, authorURL
+               $sql = "SELECT  *
                        FROM    wcf".WCF_N."_package_update
                        ".$conditions;
                $statement = WCF::getDB()->prepareStatement($sql, 20, ($this->parameters['pageNo'] - 1) * 20);
@@ -336,11 +339,50 @@ class PackageUpdateAction extends AbstractDatabaseObjectAction {
         * @return      array
         */
        public function prepareUpdate() {
+               return $this->createQueue('update');
+       }
+       
+       /**
+        * Validates parameters to prepare a package installation.
+        */
+       public function validatePrepareInstallation() {
+               WCF::getSession()->checkPermissions(array('admin.system.package.canInstallPackage'));
+               
+               $this->readString('package');
+               
+               if (isset($this->parameters['authData'])) {
+                       if (!is_array($this->parameters['authData'])) {
+                               throw new UserInputException('authData');
+                       }
+                               
+                       $this->readInteger('packageUpdateServerID', false, 'authData');
+                       $this->readString('password', false, 'authData');
+                       $this->readString('username', false, 'authData');
+                       $this->readBoolean('saveCredentials', true, 'authData');
+               }
+       }
+       
+       /**
+        * Prepares a package installation.
+        * 
+        * @return      array
+        */
+       public function prepareInstallation() {
+               return $this->createQueue('install');
+       }
+       
+       /**
+        * Creates a new package installation queue.
+        * 
+        * @param       string          $queueType
+        * @return      array
+        */
+       protected function createQueue($queueType) {
                if (isset($this->parameters['authData'])) {
                        PackageUpdateServer::storeAuthData($this->parameters['authData']['packageUpdateServerID'], $this->parameters['authData']['username'], $this->parameters['authData']['password'], $this->parameters['authData']['saveCredentials']);
                }
                
-               $scheduler = new PackageInstallationScheduler($this->parameters['packages']);
+               $scheduler = new PackageInstallationScheduler($this->parameters['package']);
                
                try {
                        $scheduler->buildPackageInstallationStack();
@@ -365,10 +407,10 @@ class PackageUpdateAction extends AbstractDatabaseObjectAction {
                                        'packageName' => $package['packageName'],
                                        'packageID' => ($package['packageID'] ?: null),
                                        'archive' => $package['archive'],
-                                       'action' => 'update'
+                                       'action' => $queueType
                                ));
                                $parentQueueID = $queue->queueID;
-                               
+               
                                if ($queueID === null) {
                                        $queueID = $queue->queueID;
                                }