Adds support for file installation of application plugins
authorMatthias Schmidt <gravatronics@live.com>
Sun, 19 May 2013 12:51:00 +0000 (14:51 +0200)
committerMatthias Schmidt <gravatronics@live.com>
Sun, 19 May 2013 12:51:00 +0000 (14:51 +0200)
Closes #1163

13 files changed:
wcfsetup/install/files/acp/templates/templateList.tpl
wcfsetup/install/files/lib/acp/page/TemplateListPage.class.php
wcfsetup/install/files/lib/data/application/Application.class.php
wcfsetup/install/files/lib/data/template/Template.class.php
wcfsetup/install/files/lib/system/WCFSetup.class.php
wcfsetup/install/files/lib/system/package/ACPTemplatesFileHandler.class.php
wcfsetup/install/files/lib/system/package/FilesFileHandler.class.php
wcfsetup/install/files/lib/system/package/PackageInstallationFileHandler.class.php
wcfsetup/install/files/lib/system/package/TemplatesFileHandler.class.php
wcfsetup/install/files/lib/system/package/plugin/ACPTemplatePackageInstallationPlugin.class.php
wcfsetup/install/files/lib/system/package/plugin/FilePackageInstallationPlugin.class.php
wcfsetup/install/files/lib/system/package/plugin/TemplatePackageInstallationPlugin.class.php
wcfsetup/setup/db/install.sql

index e0327e97e376fc282130cd0df13d6cb8e6abc1d3..88048c4453c37bcb9475c540aab57b1c54ea7d36 100644 (file)
@@ -93,7 +93,7 @@
                                                        {event name='rowButtons'}
                                                </td>
                                                <td class="columnID">{@$template->templateID}</td>
-                                               <td class="columnTitle columnTemplateName">{if $template->packageDir}[{$template->getPackageAbbreviation()}] {/if}{if $template->templateGroupID}<a href="{link controller='TemplateEdit' id=$template->templateID}{/link}">{$template->templateName}</a>{else}{$template->templateName}{/if}</td>
+                                               <td class="columnTitle columnTemplateName">{if $template->application != 'wcf'}[{$template->application}] {/if}{if $template->templateGroupID}<a href="{link controller='TemplateEdit' id=$template->templateID}{/link}">{$template->templateName}</a>{else}{$template->templateName}{/if}</td>
                                                <td class="columnDate columnLastModificationTime">{@$template->lastModificationTime|time}</td>
                                                
                                                {event name='columns'}
index e0147317c52d78926172fa3872c69b9596934b74..f99d46f1628c92602e26b75c6af29bffbaa165d4 100644 (file)
@@ -92,7 +92,7 @@ class TemplateListPage extends SortablePage {
        public function readData() {
                parent::readData();
                
-               // get template groups          
+               // get template groups
                $templateGroupList = new TemplateGroupList();
                $templateGroupList->readObjects();
                $this->availableTemplateGroups = $templateGroupList->getObjects();
index 23916d4861e5587135e4bc64b531c2decc9a1c34..e2711d567b9a1a25b7406ecf327e446120f147a8 100644 (file)
@@ -1,7 +1,11 @@
 <?php
 namespace wcf\data\application;
+use wcf\data\package\Package;
+use wcf\data\package\PackageList;
 use wcf\data\DatabaseObject;
 use wcf\system\request\RouteHandler;
+use wcf\system\exception\SystemException;
+use wcf\util\FileUtil;
 
 /**
  * Represents an application.
@@ -14,6 +18,12 @@ use wcf\system\request\RouteHandler;
  * @category   Community Framework
  */
 class Application extends DatabaseObject {
+       /**
+        * absolute page URL
+        * @var string
+        */
+       protected $pageURL = '';
+       
        /**
         * @see wcf\data\DatabaseObject::$databaseTableName
         */
@@ -30,10 +40,10 @@ class Application extends DatabaseObject {
        protected static $databaseTableIndexIsIdentity = false;
        
        /**
-        * absolute page URL
-        * @var string
+        * list of all available application directories
+        * @var array<string>
         */
-       protected $pageURL = '';
+       protected static $directories = null;
        
        /**
         * Returns absolute page URL.
@@ -47,4 +57,30 @@ class Application extends DatabaseObject {
                
                return $this->pageURL;
        }
+       
+       /**
+        * Returns the directory of the application with the given abbrevation.
+        * 
+        * @param       string          $abbreviation
+        * @return      string
+        */
+       public static function getDirectory($abbreviation) {
+               if (static::$directories === null) {
+                       static::$directories = array();
+                       
+                       // read application directories
+                       $packageList = new PackageList();
+                       $packageList->getConditionBuilder()->add('package.isApplication = ?', array(1));
+                       $packageList->readObjects();
+                       foreach ($packageList as $package) {
+                               static::$directories[Package::getAbbreviation($package->package)] = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$package->packageDir));
+                       }
+               }
+               
+               if (!isset(static::$directories[$abbreviation])) {
+                       throw new SystemException("Unknown application '".$abbreviation."'");
+               }
+               
+               return static::$directories[$abbreviation];
+       }
 }
index e7e06abb94789d8af9c371f9732630e13fb834f7..9757b08fbdfa4f3605b43b732c4d6e71808d92a9 100644 (file)
@@ -74,15 +74,6 @@ class Template extends DatabaseObject {
                return @file_get_contents($this->getPath());
        }
        
-       /**
-        * Returns the abbreviation of the package name.
-        *
-        * @return      string
-        */
-       public function getPackageAbbreviation() {
-               return Package::getAbbreviation($this->package);
-       }
-       
        /**
         * Searches in templates.
         * 
index 2744342c5431e76a2d8430e2d7c40b2d7a67555a..d6832ee049222a9073958f8066f403046620121d 100644 (file)
@@ -777,13 +777,13 @@ class WCFSetup extends WCF {
                // save acp template log
                if (!empty($acpTemplateInserts)) {
                        $sql = "INSERT INTO     wcf".WCF_N."_acp_template
-                                               (templateName)
-                               VALUES          (?)";
+                                               (templateName, application)
+                               VALUES          (?, ?)";
                        $statement = self::getDB()->prepareStatement($sql);
                        
                        self::getDB()->beginTransaction();
                        foreach ($acpTemplateInserts as $acpTemplate) {
-                               $statement->executeUnbuffered(array($acpTemplate));
+                               $statement->executeUnbuffered(array($acpTemplate, 'wcf'));
                        }
                        self::getDB()->commitTransaction();
                }
@@ -792,13 +792,13 @@ class WCFSetup extends WCF {
                // save file log
                if (!empty($fileInserts)) {
                        $sql = "INSERT INTO     wcf".WCF_N."_package_installation_file_log
-                                               (filename)
-                               VALUES          (?)";
+                                               (filename, application)
+                               VALUES          (?, ?)";
                        $statement = self::getDB()->prepareStatement($sql);
                        
                        self::getDB()->beginTransaction();
                        foreach ($fileInserts as $file) {
-                               $statement->executeUnbuffered(array($file));
+                               $statement->executeUnbuffered(array($file, 'wcf'));
                        }
                        self::getDB()->commitTransaction();
                }
index b5c131af5a853e54610a8f520db07afe49ccde70..27d23868f8da74699a2c6d782e8b65c8af5dd9ac 100644 (file)
@@ -8,7 +8,7 @@ use wcf\system\WCF;
 /**
  * File handler implementation for the installation of ACP template files.
  * 
- * @author     Alexander Ebert
+ * @author     Alexander Ebert, Matthias Schmidt
  * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
@@ -27,24 +27,21 @@ class ACPTemplatesFileHandler extends PackageInstallationFileHandler {
         */
        public function checkFiles(array $files) {
                if ($this->packageInstallation->getPackage()->package != 'com.woltlab.wcf') {
-                       $packageID = $this->packageInstallation->getPackageID();
-                       
-                       // build sql string with ACP-templateNames
-                       $fileNames = array();
-                       foreach ($files as $file) {
-                               $fileNames[] = substr($file, 0, -4);
-                       }
-                       
                        // check if files are existing already
-                       if (!empty($fileNames)) {
+                       if (!empty($files)) {
+                               foreach ($files as &$file) {
+                                       $file = substr($file, 0, -4);
+                               }
+                               unset($file);
+                               
                                // get by other packages registered files
                                $conditions = new PreparedStatementConditionBuilder();
-                               $conditions->add("packageID <> ?", array($packageID));
-                               $conditions->add("packageID IN (SELECT packageID FROM wcf".WCF_N."_package WHERE packageDir = ? AND isApplication = ?)", array($this->packageInstallation->getPackage()->packageDir, 0));
-                               $conditions->add("templateName IN (?)", array($fileNames));
+                               $conditions->add('packageID <> ?', array($this->packageInstallation->getPackageID()));
+                               $conditions->add('templateName IN (?)', array($files));
+                               $conditions->add('application = ?', array($this->application));
                                
-                               $sql = "SELECT          *
-                                       FROM            wcf".WCF_N."_".$this->tableName."
+                               $sql = "SELECT  packageID, templateName
+                                       FROM    wcf".WCF_N."_".$this->tableName."
                                        ".$conditions;
                                $statement = WCF::getDB()->prepareStatement($sql);
                                $statement->execute($conditions->getParameters());
@@ -54,12 +51,15 @@ class ACPTemplatesFileHandler extends PackageInstallationFileHandler {
                                        $lockedFiles[$row['templateName']] = $row['packageID'];
                                }
                                
-                               // check if files from installing package are in conflict with already installed files
+                               // check if acp templates from the package beeing
+                               // installed are in conflict with already installed
+                               // files
                                if (!$this->packageInstallation->getPackage()->isApplication && !empty($lockedFiles)) {
-                                       foreach ($fileNames as $key => $file) {
-                                               if (isset($lockedFiles[$file]) && $packageID != $lockedFiles[$file]) {
+                                       foreach ($files as $file) {
+                                               if (isset($lockedFiles[$file])) {
                                                        $owningPackage = new Package($lockedFiles[$file]);
-                                                       throw new SystemException("A non-application package can't overwrite template files. Only an update from the package which owns the template can do that. (Package '".$this->packageInstallation->getPackage()->package."' tries to overwrite template '".$file."', which is owned by package '".$owningPackage->package."')");
+                                                       
+                                                       throw new SystemException("A package can't overwrite templates from other packages. Only an update from the package which owns the template can do that. (Package '".$this->packageInstallation->getPackage()->package."' tries to overwrite template '".$file."', which is owned by package '".$owningPackage->package."')");
                                                }
                                        }
                                }
@@ -71,23 +71,26 @@ class ACPTemplatesFileHandler extends PackageInstallationFileHandler {
         * @see wcf\system\setup\IFileHandler::logFiles()
         */
        public function logFiles(array $files) {
-               $packageID = $this->packageInstallation->getPackageID();
-               
                // remove file extension
                foreach ($files as &$file) {
                        $file = substr($file, 0, -4);
                }
                unset($file);
                
-               // get existing templates
+               // fetch already installed acp templates
+               $conditions = new PreparedStatementConditionBuilder();
+               $conditions->add('packageID = ?', array($this->packageInstallation->getPackageID()));
+               $conditions->add('templateName IN (?)', array($files));
+               $conditions->add('application = ?', array($this->application));
+               
                $sql = "SELECT  templateName
                        FROM    wcf".WCF_N."_".$this->tableName."
-                       WHERE   packageID = ?";
+                       ".$conditions;
                $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
+               $statement->execute($conditions->getParameters());
                
-               while ($row = $statement->fetchArray()) {
-                       $index = array_search($row['templateName'], $files);
+               while ($templateName = $statement->fetchColumn()) {
+                       $index = array_search($templateName, $files);
                        
                        if ($index !== false) {
                                unset($files[$index]);
@@ -96,14 +99,15 @@ class ACPTemplatesFileHandler extends PackageInstallationFileHandler {
                
                if (!empty($files)) {
                        $sql = "INSERT INTO     wcf".WCF_N."_".$this->tableName."
-                                               (packageID, templateName)
-                               VALUES          (?, ?)";
+                                               (packageID, templateName, application)
+                               VALUES          (?, ?, ?)";
                        $statement = WCF::getDB()->prepareStatement($sql);
                        
                        foreach ($files as $file) {
                                $statement->execute(array(
-                                       $packageID,
-                                       $file
+                                       $this->packageInstallation->getPackageID(),
+                                       $file,
+                                       $this->application
                                ));
                        }
                }
index 67617ea4100d42e6ce00323e64547e08660a3b3c..fda4ac8dcbf34cd7a893fe2f1fdedb634692e887 100644 (file)
@@ -1,13 +1,15 @@
 <?php
 namespace wcf\system\package;
+use wcf\data\package\Package;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\SystemException;
 use wcf\system\WCF;
 
 /**
  * File handler implementation for the installation of regular files.
  * 
- * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @author     Matthias Schmidt, Marcel Werk
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.package
@@ -20,29 +22,30 @@ class FilesFileHandler extends PackageInstallationFileHandler {
        public function checkFiles(array $files) {
                if ($this->packageInstallation->getPackage()->package != 'com.woltlab.wcf') {
                        if (!empty($files)) {
-                               // get by other packages registered files
+                               // get registered files of other packages for the
+                               // same application
                                $conditions = new PreparedStatementConditionBuilder();
-                               $conditions->add("file_log.packageID <> ?", array($this->packageInstallation->getPackageID()));
-                               $conditions->add("file_log.filename IN (?)", array($files));
+                               $conditions->add('packageID <> ?', array($this->packageInstallation->getPackageID()));
+                               $conditions->add('filename IN (?)', array($files));
+                               $conditions->add('application = ?', array($this->application));
                                
-                               $sql = "SELECT          file_log.filename, package.packageDir
-                                       FROM            wcf".WCF_N."_package_installation_file_log file_log
-                                       LEFT JOIN       wcf".WCF_N."_package package
-                                       ON              (package.packageID = file_log.packageID)
+                               $sql = "SELECT  filename, packageID
+                                       FROM    wcf".WCF_N."_package_installation_file_log
                                        ".$conditions;
                                $statement = WCF::getDB()->prepareStatement($sql);
                                $statement->execute($conditions->getParameters());
                                $lockedFiles = array();
                                while ($row = $statement->fetchArray()) {
-                                       $lockedFiles[$row['packageDir'].$row['filename']] = true;
+                                       $lockedFiles[$row['filename']] = $row['packageID'];
                                }
                                
                                // check delivered files
                                if (!empty($lockedFiles)) {
-                                       $dir = $this->packageInstallation->getPackage()->packageDir;
                                        foreach ($files as $key => $file) {
-                                               if (isset($lockedFiles[$dir.$file])) {
-                                                       unset($files[$key]);
+                                               if (isset($lockedFiles[$file])) {
+                                                       $owningPackage = new Package($lockedFiles[$file]);
+                                                       
+                                                       throw new SystemException("A package can't overwrite files from other packages. Only an update from the package which owns the file can do that. (Package '".$this->packageInstallation->getPackage()->package."' tries to overwrite file '".$file."', which is owned by package '".$owningPackage->package."')");
                                                }
                                        }
                                }
@@ -60,39 +63,35 @@ class FilesFileHandler extends PackageInstallationFileHandler {
                
                // fetch already installed files
                $conditions = new PreparedStatementConditionBuilder();
-               $conditions->add("packageID = ?", array($this->packageInstallation->getPackageID()));
-               $conditions->add("filename IN (?)", array($files));
+               $conditions->add('packageID = ?', array($this->packageInstallation->getPackageID()));
+               $conditions->add('filename IN (?)', array($files));
+               $conditions->add('application = ?', array($this->application));
                
                $sql = "SELECT  filename
                        FROM    wcf".WCF_N."_package_installation_file_log
                        ".$conditions;
                $statement = WCF::getDB()->prepareStatement($sql);
                $statement->execute($conditions->getParameters());
-               $installedFiles = array();
-               while ($row = $statement->fetchArray()) {
-                       $installedFiles[] = $row['filename'];
-               }
                
-               // ignore files which have already been installed
-               $installFiles = array();
-               foreach ($files as $file) {
-                       if (in_array($file, $installedFiles)) {
-                               continue;
-                       }
+               while ($filename = $statement->fetchColumn()) {
+                       $index = array_search($filename, $files);
                        
-                       $installFiles[] = $file;
+                       if ($index !== false) {
+                               unset($files[$index]);
+                       }
                }
                
-               if (!empty($installFiles)) {
+               if (!empty($files)) {
                        $sql = "INSERT INTO     wcf".WCF_N."_package_installation_file_log
-                                               (packageID, filename)
-                               VALUES          (?, ?)";
+                                               (packageID, filename, application)
+                               VALUES          (?, ?, ?)";
                        $statement = WCF::getDB()->prepareStatement($sql);
                        
-                       foreach ($installFiles as $file) {
+                       foreach ($files as $file) {
                                $statement->execute(array(
                                        $this->packageInstallation->getPackageID(),
-                                       $file
+                                       $file,
+                                       $this->application
                                ));
                        }
                }
index 1e382116936676099cc0c2760162d7d085bdf13d..bcc0c1471ccc4c2ef5432ad342d6c056d9bc5b19 100644 (file)
@@ -7,13 +7,19 @@ use wcf\system\setup\IFileHandler;
  * installation.
  * 
  * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.package
  * @category   Community Framework
  */
 abstract class PackageInstallationFileHandler implements IFileHandler {
+       /**
+        * abbrevation of the application the files belong to
+        * @var array<string>
+        */
+       protected $application = '';
+       
        /**
         * active package installation dispatcher
         * @var wcf\system\package\PackageInstallationDispatcher
@@ -25,7 +31,8 @@ abstract class PackageInstallationFileHandler implements IFileHandler {
         * 
         * @param       wcf\system\package\PackageInstallationDispatcher        $packageInstallation
         */
-       public function __construct(PackageInstallationDispatcher $packageInstallation) {
+       public function __construct(PackageInstallationDispatcher $packageInstallation, $application) {
                $this->packageInstallation = $packageInstallation;
+               $this->application = $application;
        }
 }
index 82e7a72fa3aaf3c3b6d26407752c2311bb71b950..34a6bfb4df783525b4cdcad42e7745218c1ace54 100644 (file)
@@ -36,17 +36,18 @@ class TemplatesFileHandler extends ACPTemplatesFileHandler {
                $sql = "SELECT  templateName, templateID
                        FROM    wcf".WCF_N."_template
                        WHERE   packageID = ?
+                               AND application = ?
                                AND templateGroupID IS NULL";
                $statement = WCF::getDB()->prepareStatement($sql);
-               $statement->execute(array($packageID));
+               $statement->execute(array($packageID, $this->application));
                while ($row = $statement->fetchArray()) {
                        $existingTemplates[$row['templateName']] = $row['templateID'];
                }
        
                // save new templates
                $sql = "INSERT INTO     wcf".WCF_N."_template
-                                       (packageID, templateName, lastModificationTime)
-                       VALUES          (?, ?, ?)";
+                                       (packageID, templateName, lastModificationTime, application)
+                       VALUES          (?, ?, ?, ?)";
                $statement = WCF::getDB()->prepareStatement($sql);
                foreach ($files as $file) {
                        if (isset($existingTemplates[$file])) {
@@ -57,7 +58,8 @@ class TemplatesFileHandler extends ACPTemplatesFileHandler {
                        $statement->execute(array(
                                $packageID,
                                $file,
-                               TIME_NOW
+                               TIME_NOW,
+                               $this->application
                        ));
                }
                
index 739200ed54c0a061dc4caa8afbf0dd00377b0355..f16e9918c0138b5ccca0e28d16fe490a6d2ad44a 100644 (file)
@@ -1,14 +1,14 @@
 <?php
 namespace wcf\system\package\plugin;
-use wcf\system\exception\SystemException;
+use wcf\data\application\Application;
+use wcf\data\package\Package;
 use wcf\system\package\ACPTemplatesFileHandler;
 use wcf\system\WCF;
-use wcf\util\FileUtil;
 
 /**
  * Installs, updates and deletes ACP templates.
  * 
- * @author     Alexander Ebert
+ * @author     Alexander Ebert, Matthias Schmidt
  * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
@@ -27,25 +27,25 @@ class ACPTemplatePackageInstallationPlugin extends AbstractPackageInstallationPl
        public function install() {
                parent::install();
                
+               $abbreviation = 'wcf';
+               if (isset($this->instruction['attributes']['application'])) {
+                       $abbreviation = $this->instruction['attributes']['application'];
+               }
+               else if ($this->installation->getPackage()->isApplication) {
+                       $abbreviation = Package::getAbbreviation($this->installation->getPackage()->package);
+               }
+               
+               // absolute path to package dir
+               $packageDir = Application::getDirectory($abbreviation);
+               
                // extract files.tar to temp folder
                $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'acptemplates_');
                
                // create file handler
-               $fileHandler = new ACPTemplatesFileHandler($this->installation);
-               
-               // extract content of files.tar
-               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+               $fileHandler = new ACPTemplatesFileHandler($this->installation, $abbreviation);
                
-               try {
-                       $fileInstaller = $this->installation->extractFiles($packageDir.'acp/templates/', $sourceFile, $fileHandler);
-               }
-               catch (SystemException $e) {
-                       WCF::getTPL()->assign(array(
-                               'exception' => $e
-                       ));
-                       WCF::getTPL()->display('packageInstallationFileInstallationFailed');
-                       exit;
-               }
+               // extract templates
+               $this->installation->extractFiles($packageDir.'acp/templates/', $sourceFile, $fileHandler);
                
                // delete temporary sourceArchive
                @unlink($sourceFile);
@@ -55,25 +55,24 @@ class ACPTemplatePackageInstallationPlugin extends AbstractPackageInstallationPl
         * @see wcf\system\package\plugin\IPackageInstallationPlugin::uninstall()
         */
        public function uninstall() {
-               // create ACP-templates list
-               $templates = array();
-               
-               // get ACP-templates from log
-               $sql = "SELECT  *
+               // fetch ACP templates from log
+               $sql = "SELECT  templateName, application
                        FROM    wcf".WCF_N."_acp_template
                        WHERE   packageID = ?";
                $statement = WCF::getDB()->prepareStatement($sql);
                $statement->execute(array($this->installation->getPackageID()));
+               
+               $templates = array();
                while ($row = $statement->fetchArray()) {
-                       // store acp template with suffix (_$packageID)
-                       $templates[] = 'acp/templates/'.$row['templateName'].'.tpl';
+                       if (!isset($templates[$row['application']])) {
+                               $templates[$row['application']] = array();
+                       }
+                       
+                       $templates[$row['application']][] = 'acp/templates/'.$row['templateName'].'.tpl';
                }
                
-               if (!empty($templates)) {
-                       // delete template files
-                       $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
-                       $deleteEmptyDirectories = $this->installation->getPackage()->isApplication;
-                       $this->installation->deleteFiles($packageDir, $templates, false, $deleteEmptyDirectories);
+               foreach ($templates as $application => $templateNames) {
+                       $this->installation->deleteFiles(Application::getDirectory($application), $templateNames, false, $this->installation->getPackage()->isApplication);
                        
                        // delete log entries
                        parent::uninstall();
index 45f79227761e817c7b97f6f41a83936311ed75b2..923121359495efec46c367bb738ee204b4b3c832 100644 (file)
@@ -1,17 +1,17 @@
 <?php
 namespace wcf\system\package\plugin;
+use wcf\data\application\Application;
 use wcf\data\package\Package;
 use wcf\system\package\FilesFileHandler;
 use wcf\system\package\PackageInstallationDispatcher;
 use wcf\system\WCF;
-use wcf\util\FileUtil;
 use wcf\util\StyleUtil;
 
 /**
  * Installs, updates and deletes files.
  * 
- * @author     Marcel Werk
- * @copyright  2001-2012 WoltLab GmbH
+ * @author     Matthias Schmidt, Marcel Werk
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.package.plugin
@@ -29,14 +29,22 @@ class FilePackageInstallationPlugin extends AbstractPackageInstallationPlugin {
        public function install() {
                parent::install();
                
+               $abbreviation = 'wcf';
+               if (isset($this->instruction['attributes']['application'])) {
+                       $abbreviation = $this->instruction['attributes']['application'];
+               }
+               else if ($this->installation->getPackage()->isApplication) {
+                       $abbreviation = Package::getAbbreviation($this->installation->getPackage()->package);
+               }
+               
                // absolute path to package dir
-               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+               $packageDir = Application::getDirectory($abbreviation);
                
                // extract files.tar to temp folder
                $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'files_');
                
                // create file handler
-               $fileHandler = new FilesFileHandler($this->installation);
+               $fileHandler = new FilesFileHandler($this->installation, $abbreviation);
                
                // extract content of files.tar
                $fileInstaller = $this->installation->extractFiles($packageDir, $sourceFile, $fileHandler);
@@ -51,10 +59,14 @@ class FilePackageInstallationPlugin extends AbstractPackageInstallationPlugin {
                        
                        // log file
                        $sql = "INSERT INTO     wcf".WCF_N."_package_installation_file_log
-                                               (packageID, filename)
-                               VALUES          (?, 'config.inc.php')";
+                                               (packageID, filename, application)
+                               VALUES          (?, ?, ?)";
                        $statement = WCF::getDB()->prepareStatement($sql);
-                       $statement->execute(array($this->installation->getPackageID()));
+                       $statement->execute(array(
+                               $this->installation->getPackageID(),
+                               'config.inc.php',
+                               Package::getAbbreviation($this->installation->getPackage()->package)
+                       ));
                }
                
                // delete temporary sourceArchive
@@ -68,25 +80,24 @@ class FilePackageInstallationPlugin extends AbstractPackageInstallationPlugin {
         * @see wcf\system\package\plugin\IPackageInstallationPlugin::uninstall()
         */
        public function uninstall() {
-               // get absolute package dir
-               $packageDir = FileUtil::addTrailingSlash(FileUtil::unifyDirSeperator(realpath(WCF_DIR.$this->installation->getPackage()->packageDir)));
-               
-               // create file list
-               $files = array();
-               
-               // get files from log
-               $sql = "SELECT  *
+               // fetch files from log
+               $sql = "SELECT  filename, application
                        FROM    wcf".WCF_N."_package_installation_file_log
                        WHERE   packageID = ?";
                $statement = WCF::getDB()->prepareStatement($sql);
                $statement->execute(array($this->installation->getPackageID()));
+               
+               $files = array();
                while ($row = $statement->fetchArray()) {
-                       $files[] = $row['filename'];
+                       if (!isset($files[$row['application']])) {
+                               $files[$row['application']] = array();
+                       }
+                       
+                       $files[$row['application']][] = $row['filename'];
                }
                
-               if (!empty($files)) {
-                       // delete files
-                       $this->installation->deleteFiles($packageDir, $files);
+               foreach ($files as $application => $filenames) {
+                       $this->installation->deleteFiles(Application::getDirectory($application), $filenames);
                        
                        // delete log entries
                        parent::uninstall();
index 3578fe8e9e9a85c5292a98b84b8328fb5f07d980..5dac95694149d8d80c9415676270d3e4ae577134 100644 (file)
@@ -1,14 +1,15 @@
 <?php
 namespace wcf\system\package\plugin;
+use wcf\data\application\Application;
+use wcf\data\package\Package;
 use wcf\system\package\TemplatesFileHandler;
 use wcf\system\WCF;
-use wcf\util\FileUtil;
 
 /**
  * Installs, updates and deletes templates.
  * 
- * @author     Alexander Ebert
- * @copyright  2001-2011 WoltLab GmbH
+ * @author     Alexander Ebert, Matthias Schmidt
+ * @copyright  2001-2013 WoltLab GmbH
  * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
  * @package    com.woltlab.wcf
  * @subpackage system.package.plugin
@@ -26,16 +27,24 @@ class TemplatePackageInstallationPlugin extends AbstractPackageInstallationPlugi
        public function install() {
                parent::install();
                
+               $abbreviation = 'wcf';
+               if (isset($this->instruction['attributes']['application'])) {
+                       $abbreviation = $this->instruction['attributes']['application'];
+               }
+               else if ($this->installation->getPackage()->isApplication) {
+                       $abbreviation = Package::getAbbreviation($this->installation->getPackage()->package);
+               }
+               
+               // absolute path to package dir
+               $packageDir = Application::getDirectory($abbreviation);
+               
                // extract files.tar to temp folder
                $sourceFile = $this->installation->getArchive()->extractTar($this->instruction['value'], 'templates_');
                
                // create file handler
-               $fileHandler = new TemplatesFileHandler($this->installation);
-               
-               // extract content of files.tar
-               $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
+               $fileHandler = new TemplatesFileHandler($this->installation, $abbreviation);
                
-               $fileInstaller = $this->installation->extractFiles($packageDir.'templates/', $sourceFile, $fileHandler);
+               $this->installation->extractFiles($packageDir.'templates/', $sourceFile, $fileHandler);
                
                // delete temporary sourceArchive
                @unlink($sourceFile);
@@ -45,24 +54,24 @@ class TemplatePackageInstallationPlugin extends AbstractPackageInstallationPlugi
         * Uninstalls the templates of this package.
         */
        public function uninstall() {
-               // create templates list
-               $templates = array();
-               
-               // get templates from log
-               $sql = "SELECT  templateName
+               // fetch templates from log
+               $sql = "SELECT  templateName, application
                        FROM    wcf".WCF_N."_template
                        WHERE   packageID = ?";
                $statement = WCF::getDB()->prepareStatement($sql);
                $statement->execute(array($this->installation->getPackageID()));
+               
+               $templates = array();
                while ($row = $statement->fetchArray()) {
-                       $templates[] = 'templates/'.$row['templateName'].'.tpl';
+                       if (!isset($templates[$row['application']])) {
+                               $templates[$row['application']] = array();
+                       }
+                       
+                       $templates[$row['application']][] = 'templates/'.$row['templateName'].'.tpl';
                }
                
-               if (!empty($templates)) {
-                       // delete template files
-                       $packageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR.$this->installation->getPackage()->packageDir));
-                       $deleteEmptyDirectories = $this->installation->getPackage()->isApplication;
-                       $this->installation->deleteFiles($packageDir, $templates, false, $deleteEmptyDirectories);
+               foreach ($templates as $application => $templateNames) {
+                       $this->installation->deleteFiles(Application::getDirectory($application), $templateNames, false, $this->installation->getPackage()->isApplication);
                        
                        // delete log entries
                        parent::uninstall();
index 373576abf2c679772a547f24509f822a6ba918e4..3930441adec03c03104312a787857126e6d1d7cf 100644 (file)
@@ -106,8 +106,9 @@ DROP TABLE IF EXISTS wcf1_acp_template;
 CREATE TABLE wcf1_acp_template (
        templateID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
        packageID INT(10),
-       templateName VARCHAR(255) NOT NULL DEFAULT '',
-       UNIQUE KEY (packageID, templateName)
+       templateName VARCHAR(255) NOT NULL,
+       application VARCHAR(255) NOT NULL,
+       UNIQUE KEY applicationTemplate (application, templateName)
 );
 
 DROP TABLE IF EXISTS wcf1_application;
@@ -345,8 +346,9 @@ CREATE TABLE wcf1_package_exclusion (
 DROP TABLE IF EXISTS wcf1_package_installation_file_log;
 CREATE TABLE wcf1_package_installation_file_log (
        packageID INT(10),
-       filename VARCHAR(255) NOT NULL DEFAULT '',
-       UNIQUE KEY packageID (packageID, filename)
+       filename VARCHAR(255) NOT NULL,
+       application VARCHAR(255) NOT NULL,
+       UNIQUE KEY applicationFile (application, filename)
 );
 
 DROP TABLE IF EXISTS wcf1_package_installation_form;
@@ -583,11 +585,12 @@ DROP TABLE IF EXISTS wcf1_template;
 CREATE TABLE wcf1_template (
        templateID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
        packageID INT(10) NOT NULL,
-       templateName VARCHAR(255) NOT NULL DEFAULT '',
+       templateName VARCHAR(255) NOT NULL,
+       application VARCHAR(255) NOT NULL,
        templateGroupID INT(10),
        lastModificationTime INT(10) NOT NULL DEFAULT 0,
-       KEY packageID (packageID, templateName),
-       KEY templateGroupID (packageID, templateGroupID, templateName)
+       UNIQUE KEY applicationTemplate (application, templateName),
+       UNIQUE KEY templateGroupID (application, templateGroupID, templateName)
 );
 
 DROP TABLE IF EXISTS wcf1_template_group;