Ethna2.3.5とEthna2.6betaを比較する (その2)

なんでこんな比較文献学みたいなことをやってるかと言うと、version2.5をすっ飛ばして一気に2世代分もバージョンを上げるのが怖いからです。(←ビビり)

Ethna.phpの比較


2.3.5のEthna.phpをUTF8で保存してから、バージョン間の差分を見てみる。

$ diff ETHNA_2_3_5/Ethna.php-utf8 Ethna-2.6.2011010402/Ethna.php -uEbwB

--- ETHNA_2_3_5/Ethna.php-utf8	2011-04-21 03:34:47.000000000 +0900
+++ Ethna-2.6.2011010402/Ethna.php	2011-01-04 02:46:49.000000000 +0900
@@ -6,14 +6,33 @@
  *  @author     Masaki Fujimoto 
  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
  *  @package    Ethna
- *  @version    $Id$
+ *  @version    $Id: 9d6c2da5a9d4e978ea8fa675db56445d4ff26e35 $
  */
 
-/** Ethna depends on PEAR */
-require_once 'PEAR.php';
+//
+//  PEAR OS_WINDOWS constant replacement.
+//
+//  PEAR の OS_WINDOWS 定数は、defined関数で
+//  既に定義されているかをチェックしていない。
+//  よって require_once 'PEAR.php' とすると
+//  E_NOTICEが出ることから、Windows環境判定用
+//  として独自の定数を定義する
+//
+if (substr(PHP_OS, 0, 3) == 'WIN'
+ && !defined('ETHNA_OS_WINDOWS')) {
+    define('ETHNA_OS_WINDOWS', true);
+} elseif (!defined('ETHNA_OS_WINDOWS')) {
+    define('ETHNA_OS_WINDOWS', false);
+}
+//  PHP 5.1.0 以降向けの変更
+//  date.timezone が設定されていないと
+//  E_STRICT|WARNING が発生する
+if (!ini_get('date.timezone')) {
+    ini_set('date.timezone', 'Asia/Tokyo');
+}
 
 if (!defined('PATH_SEPARATOR')) {
-    if (OS_WINDOWS) {
+    if (ETHNA_OS_WINDOWS) {
         /** include_path separator(Windows) */
         define('PATH_SEPARATOR', ';');
     } else {
@@ -22,7 +41,7 @@
     }
 }
 if (!defined('DIRECTORY_SEPARATOR')) {
-    if (OS_WINDOWS) {
+    if (ETHNA_OS_WINDOWS) {
         /** directory separator(Windows) */
         define('DIRECTORY_SEPARATOR', '\\');
     } else {
@@ -32,55 +51,59 @@
 }
 
 /** バージョン定義 */
-define('ETHNA_VERSION', '2.3.5');
+define('ETHNA_VERSION', '2.6.0-beta2');
+
+/**
+ * ダミーのエラーモード
+ * PEAR非依存、かつ互換性を維持するためのもの
+ */
+define('ETHNA_ERROR_DUMMY', 'dummy');
 
 /** Ethnaベースディレクトリ定義 */
 define('ETHNA_BASE', dirname(__FILE__));
 
-require_once ETHNA_BASE . '/class/Ethna_ActionClass.php';
-require_once ETHNA_BASE . '/class/Ethna_ActionError.php';
-require_once ETHNA_BASE . '/class/Ethna_ActionForm.php';
-require_once ETHNA_BASE . '/class/Ethna_AppManager.php';
-require_once ETHNA_BASE . '/class/Ethna_AppObject.php';
-require_once ETHNA_BASE . '/class/Ethna_AppSQL.php';
-require_once ETHNA_BASE . '/class/Ethna_AppSearchObject.php';
-require_once ETHNA_BASE . '/class/Ethna_Backend.php';
-require_once ETHNA_BASE . '/class/Ethna_CacheManager.php';
-require_once ETHNA_BASE . '/class/Ethna_Config.php';
-require_once ETHNA_BASE . '/class/Ethna_Controller.php';
-require_once ETHNA_BASE . '/class/Ethna_ClassFactory.php';
-require_once ETHNA_BASE . '/class/Ethna_DB.php';
-require_once ETHNA_BASE . '/class/Ethna_Error.php';
-require_once ETHNA_BASE . '/class/Ethna_Filter.php';
-require_once ETHNA_BASE . '/class/Ethna_Handle.php';
-require_once ETHNA_BASE . '/class/Ethna_I18N.php';
-require_once ETHNA_BASE . '/class/Ethna_Logger.php';
-require_once ETHNA_BASE . '/class/Ethna_MailSender.php';
-require_once ETHNA_BASE . '/class/Ethna_Session.php';
-require_once ETHNA_BASE . '/class/Ethna_Generator.php';
-require_once ETHNA_BASE . '/class/Ethna_UrlHandler.php';
-require_once ETHNA_BASE . '/class/Ethna_Util.php';
-require_once ETHNA_BASE . '/class/Ethna_ViewClass.php';
-require_once ETHNA_BASE . '/class/View/Ethna_View_List.php';
-require_once ETHNA_BASE . '/class/Ethna_Plugin.php';
-require_once ETHNA_BASE . '/class/Ethna_Renderer.php';
-require_once ETHNA_BASE . '/class/CLI/Ethna_CLI_ActionClass.php';
+require_once ETHNA_BASE . '/class/ActionClass.php';
+require_once ETHNA_BASE . '/class/ActionError.php';
+require_once ETHNA_BASE . '/class/ActionForm.php';
+require_once ETHNA_BASE . '/class/AppManager.php';
+require_once ETHNA_BASE . '/class/AppObject.php';
+require_once ETHNA_BASE . '/class/AppSQL.php';
+require_once ETHNA_BASE . '/class/AppSearchObject.php';
+require_once ETHNA_BASE . '/class/Backend.php';
+require_once ETHNA_BASE . '/class/CacheManager.php';
+require_once ETHNA_BASE . '/class/Config.php';
+require_once ETHNA_BASE . '/class/Controller.php';
+require_once ETHNA_BASE . '/class/ClassFactory.php';
+require_once ETHNA_BASE . '/class/DB.php';
+require_once ETHNA_BASE . '/class/Error.php';
+require_once ETHNA_BASE . '/class/Filter.php';
+require_once ETHNA_BASE . '/class/Handle.php';
+require_once ETHNA_BASE . '/class/I18N.php';
+require_once ETHNA_BASE . '/class/Logger.php';
+require_once ETHNA_BASE . '/class/MailSender.php';
+require_once ETHNA_BASE . '/class/Session.php';
+require_once ETHNA_BASE . '/class/Generator.php';
+require_once ETHNA_BASE . '/class/UrlHandler.php';
+require_once ETHNA_BASE . '/class/Util.php';
+require_once ETHNA_BASE . '/class/ViewClass.php';
+require_once ETHNA_BASE . '/class/View/Json.php';
+require_once ETHNA_BASE . '/class/View/Redirect.php';
+require_once ETHNA_BASE . '/class/View/403.php';
+require_once ETHNA_BASE . '/class/View/404.php';
+require_once ETHNA_BASE . '/class/View/500.php';
+require_once ETHNA_BASE . '/class/View/List.php';
+require_once ETHNA_BASE . '/class/Plugin.php';
+require_once ETHNA_BASE . '/class/Renderer.php';
+require_once ETHNA_BASE . '/class/CLI/ActionClass.php';
 
 if (extension_loaded('soap')) {
-    require_once ETHNA_BASE . '/class/SOAP/Ethna_SOAP_ActionForm.php';
-    require_once ETHNA_BASE . '/class/SOAP/Ethna_SOAP_Gateway.php';
-    require_once ETHNA_BASE . '/class/SOAP/Ethna_SOAP_GatewayGenerator.php';
-    require_once ETHNA_BASE . '/class/SOAP/Ethna_SOAP_Util.php';
-    require_once ETHNA_BASE . '/class/SOAP/Ethna_SOAP_WsdlGenerator.php';
+    require_once ETHNA_BASE . '/class/SOAP/ActionForm.php';
+    require_once ETHNA_BASE . '/class/SOAP/Gateway.php';
+    require_once ETHNA_BASE . '/class/SOAP/GatewayGenerator.php';
+    require_once ETHNA_BASE . '/class/SOAP/Util.php';
+    require_once ETHNA_BASE . '/class/SOAP/WsdlGenerator.php';
 }
 
-/** クライアント言語定義: 英語 */
-define('LANG_EN', 'en');
-
-/** クライアント言語定義: 日本語 */
-define('LANG_JA', 'ja');
-
-
 /** ゲートウェイ: WWW */
 define('GATEWAY_WWW', 1);
 
@@ -286,10 +309,13 @@
 /** エラーコード: プラグインエラー(その他) */
 define('E_PLUGIN_GENERAL', 197);
 
-if (defined('E_STRICT') == false) {
     /** PHP 5との互換保持定義 */
+if (defined('E_STRICT') == false) {
     define('E_STRICT', 2048);
 }
+if (defined('E_DEPRECATED') == false) {
+    define('E_DEPRECATED', 8192);
+}
 
 /** Ethnaグローバル変数: エラーコールバック関数 */
 $GLOBALS['_Ethna_error_callback_list'] = array();
@@ -306,13 +332,37 @@
  *  @access     public
  *  @package    Ethna
  */
-class Ethna extends PEAR
+class Ethna
 {
-    /**#@+
-     *  @access private
+    /**
+     *  渡されたオブジェクトが Ethna_Error オブジェクト
+     *  またはそのサブクラスのオブジェクトかどうかチェックします。
+     *
+     *  @param mixed  $data    チェックする変数
+     *  @param mixed  $msgcode チェックするエラーメッセージまたはエラーコード  
+     *  @return mixed 変数が、Ethna_Error の場合に TRUEを返します。
+     *                第2引数が設定された場合は、さらに 所与された $msgcode
+     *                を含む場合のみ TRUEを返します。
+     *  @static
      */
+    public static function isError($data, $msgcode = NULL)
+    {
+        if (!is_object($data)) {
+            return false;
+        }
 
-    /**#@-*/
+        $class_name = get_class($data);
+        if (strcasecmp($class_name, 'Ethna_Error') === 0
+         || is_subclass_of($data, 'Ethna_Error')) {
+            if ($msgcode == NULL) {
+                return true;
+            } elseif ($data->getCode() == $msgcode) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 
     /**
      *  Ethna_Errorオブジェクトを生成する(エラーレベル:E_USER_ERROR)
@@ -322,7 +372,7 @@
      *  @param  int     $code               エラーコード
      *  @static
      */
-    function &raiseError($message, $code = E_GENERAL)
+    public static function raiseError($message, $code = E_GENERAL)
     {
         $userinfo = null;
         if (func_num_args() > 2) {
@@ -331,7 +381,8 @@
                 $userinfo = $userinfo[0];
             }
         }
-        return PEAR::raiseError($message, $code, PEAR_ERROR_RETURN, E_USER_ERROR, $userinfo, 'Ethna_Error');
+        $error = new Ethna_Error($message, $code, ETHNA_ERROR_DUMMY, E_USER_ERROR, $userinfo, 'Ethna_Error');
+        return $error;
     }
 
     /**
@@ -342,7 +393,7 @@
      *  @param  int     $code               エラーコード
      *  @static
      */
-    function &raiseWarning($message, $code = E_GENERAL)
+    public static function raiseWarning($message, $code = E_GENERAL)
     {
         $userinfo = null;
         if (func_num_args() > 2) {
@@ -351,7 +402,9 @@
                 $userinfo = $userinfo[0];
             }
         }
-        return PEAR::raiseError($message, $code, PEAR_ERROR_RETURN, E_USER_WARNING, $userinfo, 'Ethna_Error');
+
+        $error = new Ethna_Error($message, $code, ETHNA_ERROR_DUMMY, E_USER_WARNING, $userinfo, 'Ethna_Error');
+        return $error;
     }
 
     /**
@@ -362,7 +415,7 @@
      *  @param  int     $code               エラーコード
      *  @static
      */
-    function &raiseNotice($message, $code = E_GENERAL)
+    public static function raiseNotice($message, $code = E_GENERAL)
     {
         $userinfo = null;
         if (func_num_args() > 2) {
@@ -371,7 +424,9 @@
                 $userinfo = $userinfo[0];
             }
         }
-        return PEAR::raiseError($message, $code, PEAR_ERROR_RETURN, E_USER_NOTICE, $userinfo, 'Ethna_Error');
+
+        $error = new Ethna_Error($message, $code, ETHNA_ERROR_DUMMY, E_USER_NOTICE, $userinfo, 'Ethna_Error');
+        return $error;
     }
 
     /**
@@ -381,7 +436,7 @@
      *  @param  mixed   string:コールバック関数名 array:コールバッククラス(名|オブジェクト)+メソッド名
      *  @static
      */
-    function setErrorCallback($callback)
+    public static function setErrorCallback($callback)
     {
         $GLOBALS['_Ethna_error_callback_list'][] = $callback;
     }
@@ -392,7 +447,7 @@
      *  @access public
      *  @static
      */
-    function clearErrorCallback()
+    public static function clearErrorCallback()
     {
         $GLOBALS['_Ethna_error_callback_list'] = array();
     }
@@ -404,7 +459,7 @@
      *  @param  object  Ethna_Error     Ethna_Errorオブジェクト
      *  @static
      */
-    function handleError(&$error)
+    public static function handleError(&$error)
     {
         for ($i = 0; $i < count($GLOBALS['_Ethna_error_callback_list']); $i++) {
             $callback =& $GLOBALS['_Ethna_error_callback_list'][$i];
@@ -417,10 +472,11 @@
                 // perform some more checks?
                 $object->$method($error);
             } else {
+                //  call statically
                 call_user_func($callback, $error);
             }
         }
     }
 }
 // }}}
-?>
+


思ったほど差異がなくて安心した。

特徴的なことは、
1. Ethna_ActionClass.php → ActionClass.php ("Ethna_"がとれた)
2. PEARクラスを継承しなくなった。
3. public staticがついた

くらいでしょうか。

新登場の定数ETHNA_ERROR_DUMMYは何に使うのか?が若干気になるところではあります。

staticメソッドについては、アプリ側の方で万が一$obj->raiseError()などとしていたら、バージョンアップ時に自爆してしまうので注意が必要です。
grep検索して全部調べておかねば・・・。

追記

私が管理しているアプリで、Ethna.phpのみをバージョンアップしてみた。(2.3.5→2.6beta2)
テストした結果、$obj->raiseErrorなどとしている箇所はなかったので、staticメソッドは問題ありませんでした。

逆に問題になったのは、戻り値がリファレンスでなくなったこと。
つまり、この変更。
&raiseError($message, $code = E_GENERAL)
↓
 raiseError($message, $code = E_GENERAL)

これのせいでNoticeが出た。
調べてみたら、 Ethna_Plugin_Validator_Requiredで function &validate()というのがあり、そのメソッドがreturn Ethna::raiseErrorしているのが原因。
リファレンスを返すよ~と宣言しておきながら、リファレンスでない変数を返しているのがよくないということか。
これはPluginをバージョンアップすれば解決すると思われる。
カテゴリ: