OSDN Git Service

- add Ethna_PearWrapper.
authorichii386 <ichii386@2ef88817-412d-0410-a32c-8029a115e976>
Thu, 3 Aug 2006 04:32:31 +0000 (04:32 +0000)
committerichii386 <ichii386@2ef88817-412d-0410-a32c-8029a115e976>
Thu, 3 Aug 2006 04:32:31 +0000 (04:32 +0000)
- add install-plugin-local handler etc.
- use Ethna_Handle::getAppController() etc. in generating skelton

12 files changed:
.ethna [new file with mode: 0644]
CHANGES
class/Ethna_PearWrapper.php [new file with mode: 0644]
class/Ethna_SkeltonGenerator.php
class/Plugin/Handle/Ethna_Plugin_Handle_InfoPluginLocal.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_InfoPluginMaster.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_InstallPluginLocal.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_InstallPluginMaster.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_ListPluginLocal.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_ListPluginMaster.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_UninstallPluginLocal.php [new file with mode: 0644]
class/Plugin/Handle/Ethna_Plugin_Handle_UninstallPluginMaster.php [new file with mode: 0644]

diff --git a/.ethna b/.ethna
new file mode 100644 (file)
index 0000000..52da908
--- /dev/null
+++ b/.ethna
@@ -0,0 +1,3 @@
+[repositry]
+channel_master = "pear.ethna.jp"
+channel_local = "pear.ethna.jp"
diff --git a/CHANGES b/CHANGES
index b0088ba..84eb8cd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,16 @@
 
 *** features
 
+- Ethna¤Î¥Ñ¥Ã¥±¡¼¥¸¥·¥¹¥Æ¥à¤òÄɲÃ
+-- ethnaÍѤÎpear channel¤«¤é¥×¥é¥°¥¤¥ó¤Î¥Ñ¥Ã¥±¡¼¥¸¤ò¥¤¥ó¥¹¥È¡¼¥ë¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹
+-- Ethna_PearWrapper, Ethna_Plugin_Handle_{Install,Info,List,Uninstall}_Plugin_{Master,Local}¤òÄɲÃ
+-- local: ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó(¥×¥í¥¸¥§¥¯¥È)¤Î¥Ç¥£¥ì¥¯¥È¥ê¡¢master: EthnaËÜÂΤΤ¢¤ë¥Ç¥£¥ì¥¯¥È¥ê¤Î¥¤¥á¡¼¥¸¤Ç¤¹
+-- PearWrapper¤Ïethna¥³¥Þ¥ó¥É(Handle)¤«¤é¸Æ¤Ó½Ð¤µ¤ì¤ë¤³¤È¤¬Á°Äó
+-- Ethna_SkeltonGenerator¤Ë¤¢¤Ã¤¿¥á¥½¥Ã¥É¤òEthna_Handle¤Ë°ÜÆ°¡¢¾¯¤·ÄɲÃ
+
+- ¥¨¥é¡¼¥Ï¥ó¥É¥ê¥ó¥°Êý¿Ë¤ò¿¾¯Êѹ¹
+-- @±é»»»Ò¤ò»È¤Ã¤¿¥¨¥é¡¼ÍÞÀ©¤òÇÑ»ß
+
 - [breaking B.C.] Ethna_ClassFactory¤Î¥ê¥Õ¥¡¥¯¥¿¥ê¥ó¥°
 -- Ethna_Backend::getObject()¥á¥½¥Ã¥É¤òÄɲä·¤Þ¤·¤¿
 -- ¤³¤ì¤Ë¤è¤ê¡¢Ethna_Controller¤Î$class¥á¥ó¥Ð¤Ë
 - ethna¥³¥Þ¥ó¥É¤Ë¥¢¥¯¥·¥ç¥ó̾¡¢¥Ó¥å¡¼Ì¾¤Î¥Á¥§¥Ã¥¯½èÍý¤òÄɲÃ(Ethna_Controller::checkActionName(), Ethna_Controller::checkViewName()¤òÄɲÃ)
 - Ethna_CacheManager_Memcache(¥­¥ã¥Ã¥·¥å¥Þ¥Í¡¼¥¸¥ã¤Îmemcache¥µ¥Ý¡¼¥È)ÄɲÃ
 
+
 *** bug fixes
 
+- ¥³¥ó¥È¥í¡¼¥é¤¬Ê£¿ô¤¢¤ë¤È¤­¤Ëset_error_handler()¤¬²¿ÅÙ¤â¼Â¹Ô¤µ¤ì¤ë¤Î¤ò²óÈò
+- CacheManager_Localfile¤Î@stat¤Ç¤ÎWARNING¤ò²óÈò
+- Ethna_Plugin_Validator_Custom¤Ç¥¨¥é¡¼¤¬2½ÅÅÐÏ¿¤µ¤ì¤Æ¤¤¤¿¤Î¤ò½¤Àµ
+- ¥×¥é¥°¥¤¥ó¤Î¿Æ¥¯¥é¥¹¤¬¤Ê¤¤¤È¤­¤Ë¥¨¥é¡¼¤Ë¤Ê¤Ã¤Æ¤¤¤¿¤Î¤ò½¤Àµ
 - Ethna_DB_PEAR, Ethna_AppObject¤ÎWARNING¤ò²óÈò([ethna-users:0383])
 - Windows¤Ç¥Û¡¼¥à¥Ç¥£¥ì¥¯¥È¥ê¤Î.ethna¥Õ¥¡¥¤¥ë¤¬»²¾È¤µ¤ì¤Ê¤¤ÌäÂê¤ò½¤Àµ
 - session_start¤·¤Æ¤¤¤Ê¤¤¤Èrestore¥á¥½¥Ã¥É¤¬¤¦¤Þ¤¯Æ°¤«¤Ê¤¤ÌäÂê¤ò½¤Àµ
diff --git a/class/Ethna_PearWrapper.php b/class/Ethna_PearWrapper.php
new file mode 100644 (file)
index 0000000..d889048
--- /dev/null
@@ -0,0 +1,501 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *  Ethna_PearWrapper.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *  @package    Ethna
+ *  @version    $Id$
+ */
+
+include_once('PEAR.php');
+include_once('PEAR/Config.php');
+include_once('PEAR/Command.php');
+
+// {{{ Ethna_PearWrapper
+/**
+ *  wrapper class for PEAR_Command
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *  @access     public
+ *  @package    Ethna
+ */
+class Ethna_PearWrapper
+{
+    /**#@+
+     *  @access     private
+     */
+
+    /** @var    string  channel url of ethna repositry */
+    var $channel;
+
+    /** @var    object  PEAR_Config     PEAR_Config object */
+    var $config;
+
+    /** @var    object  PEAR_Registry   PEAR_Registry object */
+    var $registry;
+
+    /** @var    object  PEAR_Frontend   PEAR_Frontend(_CLI) object */
+    var $ui;
+
+    /**#@-*/
+
+    // {{{ constructor, initializer
+    /**
+     *  Ethna_PearWrapper constructor
+     *
+     *  @access public
+     */
+    function Ethna_PearWrapper()
+    {
+        $this->channel = '';
+        $this->config = null;
+        $this->registry = null;
+        $this->ui = null;
+    }
+
+    /**
+     *  setup PEAR_Config and so on.
+     *
+     *  @param  string      $target     whether 'master' or 'local'
+     *  @param  string|null $app_dir    if $target == 'local', specify the local
+     *                                  application directory.
+     *  @return true|Ethna_Error
+     *  @access private
+     */
+    function &init($target = 'master', $app_dir = null)
+    {
+        $true = true;
+
+        // setup PEAR_Frontend
+        PEAR_Command::setFrontendType('CLI');
+        $this->ui =& PEAR_Command::getFrontendObject();
+
+        // PEAR's error handling rule
+        PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array(&$this->ui, 'displayError'));
+        set_error_handler('ethna_error_handler_skip_pear');
+
+        // set channel
+        $master_setting = Ethna_Handle::getMasterSetting('repositry');
+        if (isset($master_setting["channel_{$target}"])) {
+            $this->channel = $master_setting["channel_{$target}"];
+        } else {
+            $this->channel = 'pear.ethna.jp';
+        }
+
+        // setup PEAR_Config
+        if ($target == 'master') {
+            $ret =& $this->_setMasterConfig();
+        } else {
+            $ret =& $this->_setLocalConfig($app_dir);
+        }
+        if (Ethna::isError($ret)) {
+            return $ret;
+        }
+        $this->ui->setConfig($this->config);
+
+        // setup PEAR_Registry
+        $this->registry =& $this->config->getRegistry();
+
+        // Ethna's error handling rule
+        Ethna::clearErrorCallback();
+        set_error_handler('ethna_error_handler_skip_pear');
+
+        return $true;
+    }
+
+    /**
+     *  config for master.
+     *
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &_setMasterConfig()
+    {
+        $true = true;
+
+        // setup config
+        $this->config =& PEAR_Config::singleton();
+
+        // setup channel
+        $reg =& $this->config->getRegistry();
+        if ($reg->channelExists($this->channel) == false) {
+            $ret =& $this->doChannelDiscover();
+            if (Ethna::isError($ret)) {
+                return $ret;
+            }
+        }
+
+        return $true;
+    }
+
+    /**
+     *  config for local.
+     *
+     *  @param  string|null $app_dir    local application directory.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &_setLocalConfig($app_dir)
+    {
+        $true = true;
+
+        // get application controller
+        $app_ctl =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($app_ctl)) {
+            return $app_ctl;
+        }
+
+        // determine dirs
+        $base = $app_ctl->getBaseDir();
+        $bin  = $app_ctl->getDirectory('bin');
+        $tmp  = $app_ctl->getDirectory('tmp');
+        $dirs = array(
+                'php_dir'       => "{$base}/skel",
+                'bin_dir'       => "{$bin}",
+                'cache_dir'     => "{$tmp}/.pear/cache",
+                'download_dir'  => "{$tmp}/.pear/download",
+                'temp_dir'      => "{$tmp}/.pear/temp",
+                'doc_dir'       => "{$tmp}/.pear/doc",
+                'ext_dir'       => "{$tmp}/.pear/ext",
+                'data_dir'      => "{$tmp}/.pear/data",
+                'test_dir'      => "{$tmp}/.pear/test",
+                );
+
+        // mkdir
+        foreach ($dirs as $key => $dir) {
+            if (is_dir($dir) == false) {
+                Ethna_Handle::mkdir($dir, 0755);
+            }
+        }
+
+        // return if local .pearrc exists.
+        $pearrc = "{$base}/skel/.pearrc";
+        $this->config =& PEAR_Config::singleton($pearrc);
+        if (is_file($pearrc) && is_readable($pearrc)) {
+            return $true;
+        }
+
+        // set dirs to config
+        foreach ($dirs as $key => $dir) {
+            $this->config->set($key, $dir);
+        }
+
+        // setup channel
+        $reg =& $this->config->getRegistry();
+        if ($reg->channelExists($this->channel) == false) {
+            $ret =& $this->doChannelDiscover();
+            if (Ethna::isError($ret)) {
+                return $ret;
+            }
+        }
+        $this->config->set('default_channel', $this->channel);
+
+        // write local .pearrc
+        $this->config->writeConfigFile();
+
+        return $true;
+    }
+    // }}}
+
+    // {{{ doClearCache
+    /**
+     *  do clear-cache (for local) 
+     *
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doClearCache()
+    {
+        $true = true;
+        $r =& $this->_run('clear-cache', array(), array());
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        return $true;
+    }
+    // }}}
+
+    // {{{ doChannelDiscover
+    /**
+     *  do channel-discover (for local) 
+     *
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doChannelDiscover()
+    {
+        $true = true;
+        $r =& $this->_run('channel-discover', array(), array($this->channel));
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        return $true;
+    }
+    // }}}
+
+    // {{{ isChannelExists
+    /**
+     *  whether channel discovered or not
+     *
+     *  @return bool
+     *  @access private 
+     */
+    function isChannelExists()
+    {
+        return $this->registry->channelExists($this->channel);
+    }
+    // }}}
+
+    // {{{ doChannelUpdate
+    /**
+     *  do channel-update (for local) 
+     *
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doChannelUpdate()
+    {
+        $true = true;
+        if ($this->isChannelExists() == false) {
+            $r =& $this->doChannelDiscover();
+            if (PEAR::isError($r)) {
+                return $r;
+            }
+        }
+        $r =& $this->_run('channel-update', array(), array($this->channel));
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        return $true;
+    }
+    // }}}
+
+    // {{{ doInstall
+    /**
+     *  do install
+     *
+     *  @param  string  $package    package name.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doInstall($package)
+    {
+        $true = true;
+        if ($this->isInstalled($package)) {
+            return Ethna::raiseNotice("{$this->channel}/{$package} already installed.");
+        }
+        $r =& $this->_run('install', array(), array("{$this->channel}/{$package}"));
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        if ($this->isInstalled($package) == false) {
+            return Ethna::raiseError("install failed (check permission etc): {$this->channel}/{$package}");
+        }
+        return $true;
+    }
+    // }}}
+
+    // {{{ isInstalled
+    /**
+     *  check package installed
+     *
+     *  @param  string  $package package name
+     *  @return bool
+     *  @access private 
+     */
+    function isInstalled($package)
+    {
+        return $this->registry->packageExists($package, $this->channel);
+    }
+    // }}}
+
+    // {{{ doUninstall
+    /**
+     *  do uninstall (packages installed with ethna command)
+     *
+     *  @param  string|null $app_dir    local application directory.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doUninstall($package)
+    {
+        $true = true;
+        if ($this->isInstalled($package) == false) {
+            return Ethna::raiseNotice("{$this->channel}/{$package} is not installed.");
+        }
+        $r =& $this->_run('uninstall', array(), array("{$this->channel}/{$package}"));
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        if ($this->isInstalled($package)) {
+            return Ethna::raiseNotice("uninstall failed: {$this->channel}/{$package}");
+        }
+        return $true;
+    }
+    // }}}
+
+    // {{{ getCanonicalPackageName
+    /**
+     *  get canonical package name (case sensitive)
+     *
+     *  @param  string  $package    package name.
+     *  @return string  canonical name
+     *  @access public
+     */
+    function &getCanonicalPackageName($package)
+    {
+        if ($this->isInstalled($package) == false) {
+            return Ethna::raiseNotice("{$this->channel}/{$package} is not installed.");
+        }
+        $pobj =& $this->registry->getPackage($package, $this->channel);
+        $cname = $pobj->getName();
+        return $cname;
+    }
+    // }}}
+
+    // {{{ doUpgrade
+    /**
+     *  do upgrade (packages installed with ethna command)
+     *
+     *  @param  string  $package    package name.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doUpgrade($package)
+    {
+        return $this->_run('upgrade', array(), array("{$this->channel}/{$package}"));
+    }
+    // }}}
+
+    // {{{ doInfo
+    /**
+     *  do info (packages installed with ethna command)
+     *
+     *  @param  string  $package    package name.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doInfo($package)
+    {
+        return $this->_run('info', array(), array("{$this->channel}/{$package}"));
+    }
+    // }}}
+
+    // {{{ doRemoteInfo
+    /**
+     *  do info (packages installable with ethna command)
+     *
+     *  @param  string  $package    package name.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doRemoteInfo($package)
+    {
+        return $this->_run('remote-info', array(), array("{$this->channel}/{$package}"));
+    }
+    // }}}
+
+    // {{{ doUpgradeAll
+    /**
+     *  do upgrade-all
+     *
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doUpgradeAll()
+    {
+        return $this->_run('upgrade-all', array('channel' => "{$this->channel}"), array());
+    }
+    // }}}
+
+    // {{{ doList
+    /**
+     *  do list (packages installed with ethna command)
+     *
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doList()
+    {
+        return $this->_run('list', array('channel' => $this->channel), array());
+    }
+    // }}}
+
+    // {{{ doRemoteList
+    /**
+     *  do remote-list (packages installable with ethna command)
+     *
+     *  @param  string|null $app_dir    local application directory.
+     *  @return true|Ethna_Error
+     *  @access private 
+     */
+    function &doRemoteList()
+    {
+        return $this->_run('remote-list', array('channel' => $this->channel), array());
+    }
+    // }}}
+
+    // {{{ subroutines.
+    /**
+     *  run PEAR_Command.
+     *
+     *  @param  string  $command    command name
+     *  @param  array   $options    options
+     *  @param  array   $params     parameters
+     *  @return true|Ethna_Error
+     *  @access private 
+     *  @see PEAR_Command_Common::run, etc.
+     */
+    function &_run($command, $options, $params)
+    {
+        if ($this->config === null) {
+            return Ethna::raiseError('configuration not initialized.');
+        }
+
+        $true = true;
+
+        $cmd =& PEAR_Command::factory($command, $this->config);
+        if (PEAR::isError($cmd)) {
+            return $cmd;
+        }
+        $ret =& $cmd->run($command, $options, $params);
+        if (PEAR::isError($ret)) {
+            return $ret;
+        }
+
+        return $true;
+    }
+
+    /**
+     *  provide yes-or-no dialog.
+     *
+     *  @return bool
+     *  @access public
+     */
+    function confirmDialog($message, $default = 'yes')
+    {
+        $ret = $this->ui->userConfirm($message);
+        return $ret;
+    }
+    // }}}
+
+}
+// }}}
+
+// {{{ ethna_error_handler_skip_pear
+/**
+ *  skip error messages raised with '@expr' in PEAR codes.
+ */
+function ethna_error_handler_skip_pear($errno, $errstr, $errfile, $errline)
+{
+    if (defined('PEAR_CONFIG_DEFAULT_PHP_DIR') === false
+        || strpos($errfile, PEAR_CONFIG_DEFAULT_PHP_DIR . '/PEAR')   !== 0
+        && strpos($errfile, PEAR_CONFIG_DEFAULT_PHP_DIR . '/System') !== 0) {
+        ethna_error_handler($errno, $errstr, $errfile, $errline);
+    }
+}
+// }}}
+
+?>
index 6a4d1b3..d9545b7 100644 (file)
@@ -155,15 +155,12 @@ class Ethna_SkeltonGenerator
      */
     function generateActionSkelton($action_name, $app_dir, $gateway = GATEWAY_WWW)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $action_dir = $c->getActiondir($gateway);
         $action_class = $c->getDefaultActionClass($action_name, $gateway);
         $action_form = $c->getDefaultFormClass($action_name, $gateway);
@@ -179,7 +176,7 @@ class Ethna_SkeltonGenerator
         $user_macro = $this->_getUserMacro();
         $macro = array_merge($macro, $user_macro);
 
-        $this->_mkdir(dirname("$action_dir$action_path"), 0755);
+        Ethna_Handle::mkdir(dirname("$action_dir$action_path"), 0755);
 
         switch ($gateway) {
         case GATEWAY_WWW:
@@ -212,15 +209,12 @@ class Ethna_SkeltonGenerator
      */
     function generateViewSkelton($forward_name, $app_dir)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $view_dir = $c->getViewdir();
         $view_class = $c->getDefaultViewClass($forward_name, false);
         $view_path = $c->getDefaultViewPath($forward_name, false);
@@ -234,7 +228,7 @@ class Ethna_SkeltonGenerator
         $user_macro = $this->_getUserMacro();
         $macro = array_merge($macro, $user_macro);
 
-        $this->_mkdir(dirname("$view_dir/$view_path"), 0755);
+        Ethna_Handle::mkdir(dirname("$view_dir/$view_path"), 0755);
 
         if (file_exists("$view_dir$view_path")) {
             printf("file [%s] already exists -> skip\n", "$view_dir$view_path");
@@ -255,15 +249,12 @@ class Ethna_SkeltonGenerator
      */
     function generateCliSkelton($action_name, $app_dir)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $app_dir = $c->getDirectory('app');
         $bin_dir = $c->getDirectory('bin');
         $cli_file = sprintf("%s/%s.%s", $bin_dir, $action_name, $c->getExt('php'));
@@ -296,15 +287,12 @@ class Ethna_SkeltonGenerator
      */
     function generateTemplateSkelton($forward_name, $app_dir)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $tpl_dir = $c->getTemplatedir();
         if ($tpl_dir{strlen($tpl_dir)-1} != '/') {
             $tpl_dir .= '/';
@@ -315,7 +303,7 @@ class Ethna_SkeltonGenerator
         // add '_' for tpl and no user macro for tpl
         $macro['_project_id'] = $c->getAppId();
 
-        $this->_mkdir(dirname("$tpl_dir/$tpl_path"), 0755);
+        Ethna_Handle::mkdir(dirname("$tpl_dir/$tpl_path"), 0755);
 
         if (file_exists("$tpl_dir$tpl_path")) {
             printf("file [%s] already exists -> skip\n", "$tpl_dir$tpl_path");
@@ -336,15 +324,12 @@ class Ethna_SkeltonGenerator
      */
     function generateAppObjectSkelton($table_name, $app_dir)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $table_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($table_name));
 
         $app_dir = $c->getDirectory('app');
@@ -359,7 +344,7 @@ class Ethna_SkeltonGenerator
         $macro = array_merge($macro, $user_macro);
 
         $path = "$app_dir/$app_path";
-        $this->_mkdir(dirname($path), 0755);
+        Ethna_Handle::mkdir(dirname($path), 0755);
         if (file_exists($path)) {
             printf("file [%s] already exists -> skip\n", $path);
         } else if ($this->_generateFile("skel.app_object.php", $path, $macro) == false) {
@@ -379,15 +364,12 @@ class Ethna_SkeltonGenerator
      */
     function generateAppManagerSkelton($manager_name, $app_dir)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $manager_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($manager_name));
 
         $app_dir = $c->getDirectory('app');
@@ -402,7 +384,7 @@ class Ethna_SkeltonGenerator
         $macro = array_merge($macro, $user_macro);
 
         $path = "$app_dir/$app_path";
-        $this->_mkdir(dirname($path), 0755);
+        Ethna_Handle::mkdir(dirname($path), 0755);
         if (file_exists($path)) {
             printf("file [%s] already exists -> skip\n", $path);
         } else if ($this->_generateFile("skel.app_manager.php", $path, $macro) == false) {
@@ -422,15 +404,12 @@ class Ethna_SkeltonGenerator
      */
     function generateActionTestSkelton($action_name, $app_dir, $gateway = GATEWAY_WWW)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $action_dir = $c->getActiondir($gateway);
         $action_class = $c->getDefaultActionClass($action_name, false);
         $action_form = $c->getDefaultFormClass($action_name, false);
@@ -446,7 +425,7 @@ class Ethna_SkeltonGenerator
         $user_macro = $this->_getUserMacro();
         $macro = array_merge($macro, $user_macro);
 
-        $this->_mkdir(dirname("$action_dir$action_path"), 0755);
+        Ethna_Handle::mkdir(dirname("$action_dir$action_path"), 0755);
 
         if (file_exists("$action_dir$action_path")) {
             printf("file [%s] aleady exists -> skip\n", "$action_dir$action_path");
@@ -466,15 +445,12 @@ class Ethna_SkeltonGenerator
      */
     function generateViewTestSkelton($forward_name, $app_dir)
     {
-        // discover controller
-        $controller_class = $this->_discoverController($app_dir);
-        if (Ethna::isError($controller_class)) {
-            return $controller_class;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
 
-        $c =& new $controller_class;
-        $c->setGateway(GATEWAY_CLI);
-
         $view_dir = $c->getViewdir();
         $view_class = $c->getDefaultViewClass($forward_name, false);
         $view_path = $c->getDefaultViewPath($forward_name . "Test", false);
@@ -488,7 +464,7 @@ class Ethna_SkeltonGenerator
         $user_macro = $this->_getUserMacro();
         $macro = array_merge($macro, $user_macro);
 
-        $this->_mkdir(dirname("$view_dir/$view_path"), 0755);
+        Ethna_Handle::mkdir(dirname("$view_dir/$view_path"), 0755);
 
         if (file_exists("$view_dir$view_path")) {
             printf("file [%s] aleady exists -> skip\n", "$view_dir$view_path");
@@ -500,28 +476,73 @@ class Ethna_SkeltonGenerator
     }
 
     /**
-     *  mkdir -p
+     *  ¥×¥é¥°¥¤¥ó¤òÀ¸À®¤¹¤ë
      *
-     *  @access private
-     *  @param  string  $dir    ºîÀ®¤¹¤ë¥Ç¥£¥ì¥¯¥È¥ê
-     *  @param  int     $mode   ¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó
+     *  @access public
+     *  @param  string  $type       ¥×¥é¥°¥¤¥ó¤Î$type
+     *  @param  string  $name       ¥×¥é¥°¥¤¥ó¤Î$name
      *  @return bool    true:À®¸ù false:¼ºÇÔ
      */
-    function _mkdir($dir, $mode)
+    function generatePlugin($type, $name, $app_dir)
     {
-        if (@is_dir($dir)) {
-            return true;
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
+        $appid = $c->getAppId();
+        $plugin =& $c->getPlugin();
 
-        $parent = dirname($dir);
-        if ($dir == $parent) {
-            return true;
+        list($class, $plugin_dir, $plugin_path) = $plugin->getPluginNaming($type, $name, $appid);
+
+        $macro = array();
+        $macro['project_id'] = $appid;
+        $user_macro = $this->_getUserMacro();
+        $macro = array_merge($macro, $user_macro);
+
+        Ethna_Handle::mkdir(dirname("$plugin_dir/$plugin_path"), 0755);
+
+        if (file_exists("$plugin_dir/$plugin_path")) {
+            printf("file [%s] already exists -> skip\n", "$plugin_dir/$plugin_path");
+        } else if ($this->_generateFile("skel.plugin.{$type}_{$name}.php", "$plugin_dir/$plugin_path", $macro) == false) {
+            printf("[warning] file creation failed [%s]\n", "$plugin_dir/$plugin_path");
+        } else {
+            printf("plugin script(s) successfully created [%s]\n", "$plugin_dir/$plugin_path");
         }
-        if (is_dir($parent) == false) {
-            $this->_mkdir($parent, $mode);
+    }
+
+    /**
+     *  ¥×¥é¥°¥¤¥ó¤ò¾Ã¤¹
+     *  TODO: ¤â¤Ã¤È¤¤¤¤Êý¿Ë¤ò¹Í¤¨¤ë
+     *
+     *  @access public
+     *  @param  string  $type       ¥×¥é¥°¥¤¥ó¤Î$type
+     *  @param  string  $name       ¥×¥é¥°¥¤¥ó¤Î$name
+     *  @return bool    true:À®¸ù false:¼ºÇÔ
+     */
+    function deletePlugin($type, $name, $app_dir)
+    {
+        // get application controller
+        $c =& Ethna_Handle::getAppController($app_dir);
+        if (Ethna::isError($c)) {
+            return $c;
         }
+        $appid = $c->getAppId();
+        $plugin =& $c->getPlugin();
+
+        list($class, $plugin_dir, $plugin_path) = $plugin->getPluginNaming($type, $name, $appid);
 
-        return mkdir($dir, $mode);
+        $macro = array();
+        $macro['project_id'] = $appid;
+        $user_macro = $this->_getUserMacro();
+        $macro = array_merge($macro, $user_macro);
+
+        if (file_exists("$plugin_dir/$plugin_path")) {
+            unlink("$plugin_dir/$plugin_path");
+            printf("file [%s] successfully unlinked\n", "$plugin_dir/$plugin_path");
+        } else {
+            printf("file [%s] not found\n", "$plugin_dir/$plugin_path");
+        }
     }
 
     /**
@@ -610,46 +631,6 @@ class Ethna_SkeltonGenerator
         $user_macro = parse_ini_file("$home/.ethna");
         return $user_macro;
     }
-
-    /**
-     *  ¥³¥ó¥È¥í¡¼¥é¥Õ¥¡¥¤¥ë/¥¯¥é¥¹¤ò¸¡º÷¤¹¤ë
-     *
-     *  @access private
-     */
-    function _discoverController($app_dir)
-    {
-        $ini_file = null;
-        while (is_dir($app_dir) && $app_dir != "/") {
-            if (is_file("$app_dir/.ethna")) {
-                $ini_file = "$app_dir/.ethna";
-                break;
-            }
-            $app_dir = dirname($app_dir);
-        }
-
-        if ($ini_file === null) {
-            return Ethna::raiseError('no .ethna file found');
-        }
-        
-        $macro = parse_ini_file($ini_file);
-        if (isset($macro['controller_file']) == false || isset($macro['controller_class']) == false) {
-            return Ethna::raiseError('invalid .ethna file');
-        }
-        $file = $macro['controller_file'];
-        $class = $macro['controller_class'];
-
-        $controller_file = "$app_dir/$file";
-        if (is_file($controller_file) == false) {
-            return Ethna::raiseError("no such file $controller_file");
-        }
-
-        include_once($controller_file);
-        if (class_exists($class) == false) {
-            return Ethna::raiseError("no such class $class");
-        }
-
-        return $class;
-    }
 }
 // }}}
 ?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_InfoPluginLocal.php b/class/Plugin/Handle/Ethna_Plugin_Handle_InfoPluginLocal.php
new file mode 100644 (file)
index 0000000..75bb51f
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_InfoPluginLocal.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_InfoPluginLocal
+/**
+ *  info-plugin-local handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_InfoPluginLocal extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "show local plugin info:\n    {$this->id} [plugin type] [plugin name] ([project-base-dir])\n";
+    }
+
+    /**
+     *  info-plugin-local
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($plugin_type, $plugin_name, $app_dir) = $r;
+        $package = "Skel_Plugin_{$plugin_type}_{$plugin_name}";
+
+        // info
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('local', $app_dir);
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        $r =& $pear->doInfo($package);
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s [plugin type] [plugin name] ([project-base-dir])\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 2) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 3) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else if (count($this->arg_list) == 2) {
+            $arg_list[] = $this->arg_list[0];
+            $arg_list[] = $this->arg_list[1];
+            $arg_list[] = getcwd();
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_InfoPluginMaster.php b/class/Plugin/Handle/Ethna_Plugin_Handle_InfoPluginMaster.php
new file mode 100644 (file)
index 0000000..176789b
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_InfoPluginMaster.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_InfoPluginMaster
+/**
+ *  info-plugin-master handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_InfoPluginMaster extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "show master plugin info:\n    {$this->id} [plugin type] [plugin name]\n";
+    }
+
+    /**
+     *  info-plugin-master
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($plugin_type, $plugin_name) = $r;
+        $package = "Ethna_Plugin_{$plugin_type}_{$plugin_name}";
+
+        // info
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('master');
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+        $r =& $pear->doInfo($package);
+        if (PEAR::isError($r)) {
+            return $r;
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s [plugin type] [plugin name]\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 2) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 2) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_InstallPluginLocal.php b/class/Plugin/Handle/Ethna_Plugin_Handle_InstallPluginLocal.php
new file mode 100644 (file)
index 0000000..416bda1
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_InstallPluginLocal.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_InstallPluginLocal
+/**
+ *  install-local-plugin handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_InstallPluginLocal extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "install local plugin to project directory:\n    {$this->id} [plugin type] [plugin name] ([project-base-dir])\n";
+    }
+
+    /**
+     *  install-plugin-local
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($plugin_type, $plugin_name, $app_dir) = $r;
+        $package = "Skel_Plugin_{$plugin_type}_{$plugin_name}";
+
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('local', $app_dir);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        // install
+        $r =& $pear->doInstall($package);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        // get ctype, cname
+        $cpackage = $pear->getCanonicalPackageName($package);
+        if (Ethna::isError($cpackage)) {
+            return $cpackage;
+        }
+        list(,, $ctype, $cname) = explode('_', $cpackage, 4);
+
+        // generate plugin by skelton
+        $ok = $pear->confirmDialog('generate a plugin from skelton? (could overwrite files already exist)');
+        if ($ok) {
+            $sg =& new Ethna_SkeltonGenerator();
+            $r = $sg->generatePlugin($ctype, $cname, $app_dir);
+            if (Ethna::isError($r)) {
+                printf("error occurred while generating plugin. please see also following error message(s)\n\n");
+                return $r;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s [plugin type] [plugin name] ([project-base-dir])\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 2) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 3) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else if (count($this->arg_list) == 2) {
+            $arg_list[] = $this->arg_list[0];
+            $arg_list[] = $this->arg_list[1];
+            $arg_list[] = getcwd();
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_InstallPluginMaster.php b/class/Plugin/Handle/Ethna_Plugin_Handle_InstallPluginMaster.php
new file mode 100644 (file)
index 0000000..60da2d8
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_InstallPluginMaster.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_InstallPluginMaster
+/**
+ *  install-plugin-master handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_InstallPluginMaster extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "install master plugin to Ethna directory:\n    {$this->id} [plugin type] [plugin name]\n";
+    }
+
+    /**
+     *  install-plugin-master
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($plugin_type, $plugin_name) = $r;
+        $package = "Ethna_Plugin_{$plugin_type}_{$plugin_name}";
+
+        // install
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('master');
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        $r =& $pear->doInstall($package);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s [plugin type] [plugin name]\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 2) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 2) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_ListPluginLocal.php b/class/Plugin/Handle/Ethna_Plugin_Handle_ListPluginLocal.php
new file mode 100644 (file)
index 0000000..facacfe
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_ListPluginLocal.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_ListPluginLocal
+/**
+ *  list-plugin-local handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_ListPluginLocal extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "list local plugins installed on the project directory:\n    {$this->id} ([project-base-dir])\n";
+    }
+
+    /**
+     *  list-plugin-local
+     *  TODO: pear list ¤·¤Æ¤¤¤ë¤À¤±¤Ê¤Î¤ò plugin specific ¤Ë¤¹¤ë
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($app_dir) = $r;
+
+        // list
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('local', $app_dir);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        $r =& $pear->doList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s ([project-base-dir])\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 0) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 1) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else if (count($this->arg_list) == 0) {
+            $arg_list[] = getcwd();
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_ListPluginMaster.php b/class/Plugin/Handle/Ethna_Plugin_Handle_ListPluginMaster.php
new file mode 100644 (file)
index 0000000..1c19718
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_ListPluginMaster.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_ListPluginMaster
+/**
+ *  list-plugin-master handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_ListPluginMaster extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "list master plugins installed on Ethna directory:\n    {$this->id}\n";
+    }
+
+    /**
+     *  list-plugin-master
+     *  TODO: pear list ¤·¤Æ¤¤¤ë¤À¤±¤Ê¤Î¤ò plugin specific ¤Ë¤¹¤ë
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        // list
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('master');
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        $r =& $pear->doList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 0) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 0) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_UninstallPluginLocal.php b/class/Plugin/Handle/Ethna_Plugin_Handle_UninstallPluginLocal.php
new file mode 100644 (file)
index 0000000..8ee32fd
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_UninstallPluginLocal.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_UninstallPluginLocal
+/**
+ *  uninstall-plugin-local handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_UninstallPluginLocal extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "uninstall local plugin from project directory:\n    {$this->id} [plugin type] [plugin name] ([project-base-dir])\n";
+    }
+
+    /**
+     *  uninstall-plugin-local
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($plugin_type, $plugin_name, $app_dir) = $r;
+        $package = "Skel_Plugin_{$plugin_type}_{$plugin_name}";
+
+        // initialize
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('local', $app_dir);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        // get ctype, cname
+        $cpackage = $pear->getCanonicalPackageName($package);
+        if (Ethna::isError($cpackage)) {
+            return $cpackage;
+        }
+        list(,, $ctype, $cname) = explode('_', $cpackage, 4);
+
+        // uninstall
+        $r = $pear->doUninstall($package);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        // delete generated plugin
+        $ok = $pear->confirmDialog('delete plugin generated from skelton? (could delete locally modified files)');
+        if ($ok) {
+            $sg =& new Ethna_SkeltonGenerator();
+            $r = $sg->deletePlugin($ctype, $cname, $app_dir);
+            if (Ethna::isError($r)) {
+                printf("error occurred while deleting plugin. please see also following error message(s)\n\n");
+                return $r;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s [plugin type] [plugin name] ([project-base-dir])\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 2) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 3) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else if (count($this->arg_list) == 2) {
+            $arg_list[] = $this->arg_list[0];
+            $arg_list[] = $this->arg_list[1];
+            $arg_list[] = getcwd();
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+?>
diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_UninstallPluginMaster.php b/class/Plugin/Handle/Ethna_Plugin_Handle_UninstallPluginMaster.php
new file mode 100644 (file)
index 0000000..22a1479
--- /dev/null
@@ -0,0 +1,92 @@
+<?php
+// vim: foldmethod=marker
+/**
+ *     Ethna_Plugin_Handle_UninstallPluginMaster.php
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @license        http://www.opensource.org/licenses/bsd-license.php The BSD License
+ *     @package        Ethna
+ *     @version        $Id$
+ */
+
+include_once(ETHNA_BASE . '/class/Ethna_PearWrapper.php');
+
+// {{{ Ethna_Plugin_Handle_UninstallPluginMaster
+/**
+ *  uninstall-plugin-master handler
+ *
+ *  @author     ICHII Takashi <ichii386@schweetheart.jp>
+ *     @access         public
+ *     @package        Ethna
+ */
+class Ethna_Plugin_Handle_UninstallPluginMaster extends Ethna_Plugin_Handle
+{
+    /**
+     *  get handler's description
+     *
+     *  @access public
+     */
+    function getDescription()
+    {
+        return "uninstall master plugin from Ethna directory:\n    {$this->id} [plugin type] [plugin name]\n";
+    }
+
+    /**
+     *  uninstall-plugin-master
+     *
+     *  @access public
+     */
+    function perform()
+    {
+        $r = $this->_validateArgList();
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        list($plugin_type, $plugin_name) = $r;
+        $package = "Ethna_Plugin_{$plugin_type}_{$plugin_name}";
+
+        // uninstall
+        $pear =& new Ethna_PearWrapper();
+        $r =& $pear->init('master');
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+        $r =& $pear->doUninstall($package);
+        if (Ethna::isError($r)) {
+            return $r;
+        }
+
+        return true;
+    }
+
+    /**
+     *  show usage
+     *
+     *  @access public
+     */
+    function usage()
+    {
+        printf("usage:\nethna %s [plugin type] [plugin name]\n\n", $this->id);
+    }
+
+    /**
+     *  check arguments
+     *
+     *  @access private
+     */
+    function _validateArgList()
+    {
+        $arg_list = array();
+        if (count($this->arg_list) < 2) {
+            return Ethna::raiseError('too few argments', 'usage');
+        } else if (count($this->arg_list) > 2) {
+            return Ethna::raiseError('too many argments', 'usage');
+        } else {
+            $arg_list = $this->arg_list;
+        }
+
+        return $arg_list;
+    }
+}
+// }}}
+?>