Extract the PEAR specific parts of the package.xml update process into the Pear wrappers.
authorGunnar Wrobel <p@rdus.de>
Tue, 12 Oct 2010 08:06:05 +0000 (10:06 +0200)
committerGunnar Wrobel <p@rdus.de>
Wed, 13 Oct 2010 19:14:42 +0000 (21:14 +0200)
components/lib/Components/Config/Cli.php
components/lib/Components/Module/CiSetup.php
components/lib/Components/Pear/Factory.php
components/lib/Components/Pear/Package.php
components/lib/Components/Runner/PearPackageXml.php
components/test/Components/Integration/Components/Module/PearPackageXmlTest.php [new file with mode: 0644]
components/test/Components/Integration/ComponentsTest.php

index 7b46ec5..3b8b768 100644 (file)
@@ -100,6 +100,16 @@ implements Components_Config
                 )
             )
         );
+        $parser->addOption(
+            new Horde_Argv_Option(
+                '-R',
+                '--pearrc',
+                array(
+                    'action' => 'store',
+                    'help'   => 'the path to the configuration of the PEAR installation you want to use for all PEAR based actions (leave empty to use your system default PEAR environment).'
+                )
+            )
+        );
     }
 
     /**
index 1561ff0..f528b2a 100644 (file)
@@ -67,14 +67,6 @@ extends Components_Module_Base
                     'help'   => 'the path to the PEAR installation holding the required analysis tools'
                 )
             ),
-            new Horde_Argv_Option(
-                '-R',
-                '--pearrc',
-                array(
-                    'action' => 'store',
-                    'help'   => 'the path to the configuration of the PEAR installation'
-                )
-            ),
         );
     }
 
index 6fed6c7..99a84ce 100644 (file)
@@ -77,5 +77,19 @@ class Components_Pear_Factory
         return $package;
     }
 
+    /**
+     * Create a package representation for the default PEAR environment.
+     *
+     * @param string $package_file The path of the package XML file.
+     *
+     * @return NULL
+     */
+    public function createPackageForDefaultLocation($package_file)
+    {
+        $package = $this->_dependencies->getInstance('Components_Pear_Package');
+        $package->setEnvironment($this->_dependencies->getInstance('Components_Pear_InstallLocation'));
+        $package->setPackageXml($package_file);
+        return $package;
+    }
 
 }
\ No newline at end of file
index cadd580..8b93d12 100644 (file)
@@ -56,6 +56,13 @@ class Components_Pear_Package
     private $_package_file;
 
     /**
+     * The writeable package representation.
+     *
+     * @param PEAR_PackageFileManager2
+     */
+    private $_package_rw_file;
+
+    /**
      * Constructor.
      *
      * @param Component_Output $output The output handler.
@@ -107,11 +114,9 @@ class Components_Pear_Package
      *
      * @return PEAR_PackageFile
      */
-    public function getPackageFile()
+    private function _getPackageFile()
     {
-        if ($this->_environment === null || $this->_package_xml_path === null) {
-            throw new Components_Exception('You need to set the environment and the path to the package file first!');
-        }
+        $this->_checkSetup();
         if ($this->_package_file === null) {
             $config = $this->getEnvironment()->getPearConfig();
             $pkg = new PEAR_PackageFile($config);
@@ -124,12 +129,153 @@ class Components_Pear_Package
     }
 
     /**
+     * Return a writeable PEAR Package representation.
+     *
+     * @return PEAR_PackageFileManager2
+     */
+    private function _getPackageRwFile()
+    {
+        $this->_checkSetup();
+        if ($this->_package_rw_file === null) {
+            /**
+             * Ensure we setup the PEAR_Config according to the PEAR environment
+             * the user set.
+             */
+            $this->getEnvironment()->getPearConfig();
+
+            if (!class_exists('PEAR_PackageFileManager2')) {
+                throw new Components_Exception(
+                    'The Package "PEAR_PackageFileManager2" is missing in the PEAR environment. Please install it so that you can run this action.'
+                );
+            }
+
+            $this->_package_rw_file = PEAR_PackageFileManager2::importOptions(
+                $this->_package_xml_path,
+                array(
+                    'packagedirectory' => dirname($this->_package_xml_path),
+                    'filelistgenerator' => 'file',
+                    'clearcontents' => false,
+                    'clearchangelog' => false,
+                    'simpleoutput' => true,
+                    'ignore' => array('*~', 'conf.php', 'CVS/*'),
+                    'include' => '*',
+                    'dir_roles' =>
+                    array(
+                        'doc'       => 'doc',
+                        'example'   => 'doc',
+                        'js'        => 'horde',
+                        'lib'       => 'php',
+                        'migration' => 'data',
+                        'script'    => 'script',
+                        'test'      => 'test',
+                    ),
+                )
+            );
+
+            if ($this->_package_rw_file instanceOf PEAR_Error) {
+                throw new Components_Exception($this->_package_file->getMessage());
+            }
+        }
+        return $this->_package_rw_file;
+    }
+
+    /**
+     * Validate that the required parameters for providing the package definition are set.
+     *
+     * @return NULL
+     *
+     * @throws Components_Exception In case some settings are missing.
+     */
+    private function _checkSetup()
+    {
+        if ($this->_environment === null || $this->_package_xml_path === null) {
+            throw new Components_Exception('You need to set the environment and the path to the package file first!');
+        }
+    }
+
+    /**
      * Return the description for this package.
      *
      * @return string The package description.
      */
     public function getDescription()
     {
-        return $this->getPackageFile()->getDescription();
+        return $this->_getPackageFile()->getDescription();
+    }
+
+    private function _getUpdatedPackageFile()
+    {
+        $package = $this->_getPackageRwFile();
+        /**
+         * @todo: Looks like this throws away any <replace /> tags we have in
+         * the content list. Needs to be fixed.
+         */
+        $package->generateContents();
+
+        /**
+         * This is required to clear the <phprelease><filelist></filelist></phprelease>
+         * section.
+         */
+        $package->setPackageType('php');
+
+        $contents = $package->getContents();
+        $files = $contents['dir']['file'];
+
+        foreach ($files as $file) {
+            $components = explode('/', $file['attribs']['name'], 2);
+            switch ($components[0]) {
+            case 'doc':
+            case 'example':
+            case 'lib':
+            case 'test':
+            case 'data':
+                $package->addInstallAs(
+                    $file['attribs']['name'], $components[1]
+                );
+            break;
+            case 'js':
+                $package->addInstallAs(
+                    $file['attribs']['name'], $file['attribs']['name']
+                );
+            break;
+            case 'migration':
+                $components = explode('/', $components[1]);
+                array_splice($components, count($components) - 1, 0, 'migration');
+                $package->addInstallAs(
+                    $file['attribs']['name'], implode('/', $components)
+                );
+                break;
+            case 'script':
+                $filename = basename($file['attribs']['name']);
+                if (substr($filename, strlen($filename) - 4)) {
+                    $filename = substr($filename, 0, strlen($filename) - 4);
+                }
+                $package->addInstallAs(
+                    $file['attribs']['name'], $filename
+                );
+                break;
+            }
+        }
+        return $package;
     }
+
+    /**
+     * Output the updated package.xml file.
+     *
+     * @return NULL
+     */
+    public function printUpdatedPackageFile()
+    {
+        $this->_getUpdatedPackageFile()->debugPackageFile();
+    }    
+
+    /**
+     * Write the updated package.xml file to disk.
+     *
+     * @return NULL
+     */
+    public function writeUpdatedPackageFile()
+    {
+        $this->_getUpdatedPackageFile()->writePackageFile();
+    }    
 }
index 036d782..7d9d35b 100644 (file)
@@ -37,121 +37,47 @@ class Components_Runner_PearPackageXml
     private $_config;
 
     /**
-     * The package handler.
+     * The factory for PEAR handlers.
      *
-     * @var Components_Pear_Package
+     * @var Components_Factory
      */
-    private $_package;
+    private $_factory;
 
     /**
      * Constructor.
      *
      * @param Components_Config       $config  The configuration for the current job.
-     * @param Components_Pear_Package $package Package handler.
+     * @param Components_Pear_Factory $factory Generator for all
+     *                                         required PEAR components.
      */
     public function __construct(
         Components_Config $config,
-        Components_Pear_Package $package
+        Components_Pear_Factory $factory
     ) {
         $this->_config  = $config;
-        $this->_package = $package;
+        $this->_factory = $factory;
     }
 
     public function run()
     {
         $arguments = $this->_config->getArguments();
-        $package_file = $arguments[0] . '/package.xml';
-
-        $pear = new PEAR();
-        $pear->setErrorHandling(PEAR_ERROR_DIE);
-
-        if (!isset($GLOBALS['_PEAR_Config_instance'])) {
-            $GLOBALS['_PEAR_Config_instance'] = false;
-        }
-
-        $package = PEAR_PackageFileManager2::importOptions(
-            $package_file,
-            array(
-                'packagedirectory' => $arguments[0],
-                'filelistgenerator' => 'file',
-                'clearcontents' => false,
-                'clearchangelog' => false,
-                'simpleoutput' => true,
-                'ignore' => array('*~', 'conf.php', 'CVS/*'),
-                'include' => '*',
-                'dir_roles' =>
-                array(
-                    'doc'       => 'doc',
-                    'example'   => 'doc',
-                    'js'        => 'horde',
-                    'lib'       => 'php',
-                    'migration' => 'data',
-                    'script'    => 'script',
-                    'test'      => 'test',
-                ),
-            )
-        );
-
-        if ($package instanceOf PEAR_Error) {
-            throw new Components_Exception($package->getMessage());
-        }
-        /**
-         * @todo: Looks like this throws away any <replace /> tags we have in
-         * the content list. Needs to be fixed.
-         */
-        $package->generateContents();
-
-        /**
-         * This is required to clear the <phprelease><filelist></filelist></phprelease>
-         * section.
-         */
-        $package->setPackageType('php');
-
-        $contents = $package->getContents();
-        $files = $contents['dir']['file'];
-
-        foreach ($files as $file) {
-            $components = explode('/', $file['attribs']['name'], 2);
-            switch ($components[0]) {
-            case 'doc':
-            case 'example':
-            case 'lib':
-            case 'test':
-            case 'data':
-                $package->addInstallAs(
-                    $file['attribs']['name'], $components[1]
-                );
-            break;
-            case 'js':
-                $package->addInstallAs(
-                    $file['attribs']['name'], $file['attribs']['name']
-                );
-            break;
-            case 'migration':
-                $components = explode('/', $components[1]);
-                array_splice($components, count($components) - 1, 0, 'migration');
-                $package->addInstallAs(
-                    $file['attribs']['name'], implode('/', $components)
-                );
-                break;
-            case 'script':
-                $filename = basename($file['attribs']['name']);
-                if (substr($filename, strlen($filename) - 4)) {
-                    $filename = substr($filename, 0, strlen($filename) - 4);
-                }
-                $package->addInstallAs(
-                    $file['attribs']['name'], $filename
-                );
-                break;
-            }
+        if (isset($options['pearrc'])) {
+            $package = $this->_factory->createPackageForInstallLocation(
+                $arguments[0] . '/package.xml',
+                $options['pearrc']
+            );
+        } else {
+            $package = $this->_factory->createPackageForDefaultLocation(
+                $arguments[0] . '/package.xml'
+            );
         }
 
         $options = $this->_config->getOptions();
         if (!empty($options['packagexml'])) {
-            $package->debugPackageFile();
+            $package->printUpdatedPackageFile();
         }
         if (!empty($options['updatexml'])) {
-            $package->writePackageFile();
+            $package->writeUpdatedPackageFile();
         }
 
     }
diff --git a/components/test/Components/Integration/Components/Module/PearPackageXmlTest.php b/components/test/Components/Integration/Components/Module/PearPackageXmlTest.php
new file mode 100644 (file)
index 0000000..e7d78ea
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Test the PearPackageXml module.
+ *
+ * PHP version 5
+ *
+ * @category   Horde
+ * @package    Components
+ * @subpackage UnitTests
+ * @author     Gunnar Wrobel <wrobel@pardus.de>
+ * @license    http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link       http://pear.horde.org/index.php?package=Components
+ */
+
+/**
+ * Prepare the test setup.
+ */
+require_once dirname(__FILE__) . '/../../../Autoload.php';
+
+/**
+ * Test the PearPackageXml module.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category   Horde
+ * @package    Components
+ * @subpackage UnitTests
+ * @author     Gunnar Wrobel <wrobel@pardus.de>
+ * @license    http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link       http://pear.horde.org/index.php?package=Components
+ */
+class Components_Integration_Components_Module_PearPackageXmlTest
+extends Components_StoryTestCase
+{
+
+    /**
+     * @scenario
+     */
+    public function thePearpackagexmlModuleAddsThePOptionInTheHelpOutput()
+    {
+        $this->given('the default Components setup')
+            ->when('calling the package with the help option')
+            ->then('the help will contain the "p" option.');
+    }
+
+    /**
+     * @scenario
+     */
+    public function thePearpackagexmlModuleAddsTheUOptionInTheHelpOutput()
+    {
+        $this->given('the default Components setup')
+            ->when('calling the package with the help option')
+            ->then('the help will contain the "u" option.');
+    }
+
+    /**
+     * @scenario
+     */
+    public function thePOptionFailsWithoutAValidPackagePath()
+    {
+        $this->given('the default Components setup')
+            ->when('calling the package with the packagexml option and the path', '')
+            ->then('the call will fail with', 'Please specify the path of the PEAR package!');
+    }
+
+    /**
+     * @scenario
+     */
+    public function thePOptionFailsWithoutAValidDirectoryPath()
+    {
+        $this->given('the default Components setup')
+            ->when(
+                'calling the package with the packagexml option and the path',
+                dirname(dirname(dirname(dirname(__FILE__)))) . '/fixture/DOESNOTEXIST'
+            )
+            ->then('the call will fail with', 'specifies no directory');
+    }
+
+    /**
+     * @scenario
+     */
+    public function thePOptionFailsWithoutAValidPackage()
+    {
+        $this->given('the default Components setup')
+            ->when(
+                'calling the package with the packagexml option and the path',
+                dirname(dirname(dirname(dirname(__FILE__)))) . '/fixture'
+            )
+            ->then('the call will fail with', 'There is no package.xml at');
+    }
+
+    /**
+     * @scenario
+     */
+    public function thePOptionProvidesAnUpdatedPackageXml()
+    {
+        $this->given('the default Components setup')
+            ->when('calling the package with the packagexml option and a Horde element')
+            ->then('the new package.xml of the Horde element will be printed.');
+    }
+
+    /**
+     * @todo Test (and fix) the reactions to three more scenarios:
+     *  - invalid XML in the package.xml (e.g. tag missing)
+     *  - empty file list
+     *  - file list with just one entry.
+     *
+     * All three scenarios yield errors which are still hard to
+     * understand.
+     */
+
+}
\ No newline at end of file
index d6e662d..69dcd69 100644 (file)
@@ -44,27 +44,6 @@ extends Components_StoryTestCase
             ->when('calling the package with the help option')
             ->then('the help will be displayed');
     }
-
-    /**
-     * @scenario
-     */
-    public function thePearpackagexmlModuleAddsThePOptionInTheHelpOutput()
-    {
-        $this->given('the default Components setup')
-            ->when('calling the package with the help option')
-            ->then('the help will contain the "p" option.');
-    }
-
-    /**
-     * @scenario
-     */
-    public function thePearpackagexmlModuleAddsTheUOptionInTheHelpOutput()
-    {
-        $this->given('the default Components setup')
-            ->when('calling the package with the help option')
-            ->then('the help will contain the "u" option.');
-    }
-
     /**
      * @scenario
      */
@@ -75,60 +54,4 @@ extends Components_StoryTestCase
             ->then('the help will contain the "d" option.');
     }
 
-    /**
-     * @scenario
-     */
-    public function thePOptionFailsWithoutAValidPackagePath()
-    {
-        $this->given('the default Components setup')
-            ->when('calling the package with the packagexml option and the path', '')
-            ->then('the call will fail with', 'Please specify the path of the PEAR package!');
-    }
-
-    /**
-     * @scenario
-     */
-    public function thePOptionFailsWithoutAValidDirectoryPath()
-    {
-        $this->given('the default Components setup')
-            ->when(
-                'calling the package with the packagexml option and the path',
-                dirname(dirname(__FILE__)) . '/fixture/DOESNOTEXIST'
-            )
-            ->then('the call will fail with', 'specifies no directory');
-    }
-
-    /**
-     * @scenario
-     */
-    public function thePOptionFailsWithoutAValidPackage()
-    {
-        $this->given('the default Components setup')
-            ->when(
-                'calling the package with the packagexml option and the path',
-                dirname(dirname(__FILE__)) . '/fixture'
-            )
-            ->then('the call will fail with', 'There is no package.xml at');
-    }
-
-    /**
-     * @scenario
-     */
-    public function thePOptionProvidesAnUpdatedPackageXml()
-    {
-        $this->given('the default Components setup')
-            ->when('calling the package with the packagexml option and a Horde element')
-            ->then('the new package.xml of the Horde element will be printed.');
-    }
-
-    /**
-     * @todo Test (and fix) the reactions to three more scenarios:
-     *  - invalid XML in the package.xml (e.g. tag missing)
-     *  - empty file list
-     *  - file list with just one entry.
-     *
-     * All three scenarios yield errors which are still hard to
-     * understand.
-     */
-
 }
\ No newline at end of file