Source for file ClassFactory.php

Documentation is available at ClassFactory.php

  1. <?php
  2. // vim: foldmethod=marker
  3. /**
  4.  *  ClassFactory.php
  5.  *
  6.  *  @author     Masaki Fujimoto <fujimoto@php.net>
  7.  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
  8.  *  @package    Ethna
  9.  *  @version    $Id: e353c7aaa0f1cb7bbdae88b002f538e20e6abe5b $
  10.  */
  11.  
  12. // {{{ Ethna_ClassFactory
  13. /**
  14.  *  Ethnaフレームワークのオブジェクト生成ゲートウェイ
  15.  *
  16.  *  DIコンテナか、ということも考えましたがEthnaではこの程度の単純なものに
  17.  *  留めておきます。アプリケーションレベルDIしたい場合はフィルタチェインを
  18.  *  使って実現することも出来ます。
  19.  *
  20.  *  @author     Masaki Fujimoto <fujimoto@php.net>
  21.  *  @access     public
  22.  *  @package    Ethna
  23.  */
  24. {
  25.     /**#@+
  26.      *  @access private
  27.      */
  28.  
  29.     /** @protected    object  Ethna_Controller    controllerオブジェクト */
  30.     protected $controller;
  31.  
  32.     /** @protected    object  Ethna_Controller    controllerオブジェクト(省略形) */
  33.     protected $ctl;
  34.  
  35.     /** @protected    array   クラス定義 */
  36.     protected $class = array();
  37.  
  38.     /** @FIXME @protected    array   生成済みオブジェクトキャッシュ */
  39.     public $object = array();
  40.  
  41.     /** @protected    array   生成済みアプリケーションマネージャオブジェクトキャッシュ */
  42.     protected $manager = array();
  43.  
  44.     /** @protected    array   メソッド一覧キャッシュ */
  45.     protected $method_list = array();
  46.  
  47.     /**#@-*/
  48.  
  49.  
  50.     /**
  51.      *  Ethna_ClassFactoryクラスのコンストラクタ
  52.      *
  53.      *  @access public
  54.      *  @param  object  Ethna_Controller    $controller    controllerオブジェクト
  55.      *  @param  array                       $class          クラス定義
  56.      */
  57.     public function __construct($controller$class)
  58.     {
  59.         $this->controller = $controller;
  60.         $this->ctl = $controller;
  61.         $this->class = $class;
  62.     }
  63.  
  64.     /**
  65.      *  typeに対応するアプリケーションマネージャオブジェクトを返す
  66.      *  注意: typeは大文字小文字を区別しない
  67.      *         (PHP自体が、クラス名の大文字小文字を区別しないため)
  68.      *
  69.      *  @access public
  70.      *  @param  string  $type   アプリケーションマネージャー名
  71.      *  @param  bool    $weak   オブジェクトが未生成の場合の強制生成フラグ(default: false)
  72.      *  @return object  Ethna_AppManager    マネージャオブジェクト
  73.      */
  74.     function getManager($type$weak false)
  75.     {
  76.         $obj null;
  77.  
  78.         //  すでにincludeされていなければ、includeを試みる
  79.         //  ここで返されるクラス名は、AppObjectの命名規約によるもの
  80.         //
  81.         //  これは、AppObject のファイル中にAppManagerが含まれる場合が
  82.         //  あるため必要なルーチンである
  83.         $obj_class_name $this->controller->getObjectClassName($type);
  84.         if (class_exists($obj_class_name=== false{
  85.             $this->_include($obj_class_name);
  86.         }
  87.  
  88.         //  すでにincludeされていなければ、includeを試みる
  89.         //  ここで返されるクラス名は、AppManagerの命名規約によるもの
  90.         $class_name $this->controller->getManagerClassName($type);
  91.         if (class_exists($class_name=== false
  92.             && $this->_include($class_name=== false{
  93.             return $obj;  //  include 失敗。戻り値はNULL。
  94.         }
  95.  
  96.         //  メソッド情報を集める
  97.         if (isset($this->method_list[$class_name]== false{
  98.             $this->method_list[$class_nameget_class_methods($class_name);
  99.             for ($i 0$i count($this->method_list[$class_name])$i++{
  100.                 $this->method_list[$class_name][$istrtolower($this->method_list[$class_name][$i]);
  101.             }
  102.         }
  103.  
  104.         //  PHPのクラス名は大文字小文字を区別しないので、
  105.         //  同じクラス名と見做されるものを指定した場合には
  106.         //  同じインスタンスが返るようにする
  107.         $type strtolower($type);
  108.  
  109.         //  以下のルールに従って、キャッシュが利用可能かを判定する
  110.         //  利用可能と判断した場合、キャッシュされていればそれを返す
  111.         //
  112.         //  1. メソッドに getInstance があればキャッシュを利用可能と判断する
  113.         //     この場合、シングルトンかどうかは getInstance 次第
  114.         //  2. weak が true であれば、キャッシュは利用不能と判断してオブジェクトを再生成
  115.         //  3. weak が false であれば、キャッシュは利用可能と判断する(デフォルト)
  116.         if ($this->_isCacheAvailable($class_name$this->method_list[$class_name]$weak)) {
  117.             if (isset($this->manager[$type]&& is_object($this->manager[$type])) {
  118.                 return $this->manager[$type];
  119.             }
  120.         }
  121.  
  122.         //  インスタンス化のヘルパ(getInstance)があればそれを使う
  123.         if (in_array("getinstance"$this->method_list[$class_name])) {
  124.             $obj call_user_func(array($class_name'getInstance'));
  125.         else {
  126.             $backend $this->controller->getBackend();
  127.             $obj new $class_name($backend);
  128.         }
  129.  
  130.         //  生成したオブジェクトはとりあえずキャッシュする
  131.         if (isset($this->manager[$type]== false || is_object($this->manager[$type]== false{
  132.             $this->manager[$type$obj;
  133.         }
  134.  
  135.         return $obj;
  136.     }
  137.  
  138.     /**
  139.      *  クラスキーに対応するオブジェクトを返す/クラスキーが未定義の場合はAppObjectを探す
  140.      *  クラスキーとは、[Appid]_Controller#class に定められたもの。
  141.      *
  142.      *  @access public
  143.      *  @param  string  $key    [Appid]_Controller#class に定められたクラスキー
  144.      *                           このキーは大文字小文字を区別する
  145.      *                           (配列のキーとして使われているため)
  146.      *  @param  bool    $ext    オブジェクトが未生成の場合の強制生成フラグ(default: false)
  147.      *  @return object  生成されたオブジェクト(エラーならnull) 
  148.      */
  149.     function getObject($key$ext false)
  150.     {
  151.         $object null;
  152.  
  153.         $ext to_array($ext);
  154.         if (isset($this->class[$key]== false{
  155.             // app object
  156.             $class_name $this->controller->getObjectClassName($key);
  157.             $ext array_pad($ext3null);
  158.             list($key_type$key_value$prop$ext;
  159.         else {
  160.             // ethna classes
  161.             $class_name $this->class[$key];
  162.             $ext array_pad($ext1null);
  163.             list($weak$ext;
  164.         }
  165.  
  166.         //  すでにincludeされていなければ、includeを試みる
  167.         if (class_exists($class_name== false{
  168.             if ($this->_include($class_name== false{
  169.                 return $object;  //  include 失敗。返り値はnull
  170.             }
  171.         }
  172.  
  173.         //  AppObject をはじめに扱う
  174.         //  AppObject はキャッシュされないことに注意
  175.         if (isset($this->class[$key]== false{
  176.             $backend $this->controller->getBackend();
  177.             $object new $class_name($backend$key_type$key_value$prop);
  178.             return $object;
  179.         }
  180.  
  181.         //  Ethna_Controllerで定義されたクラスキーの場合
  182.         //  はメソッド情報を集める
  183.         if (isset($this->method_list[$class_name]== false{
  184.             $this->method_list[$class_nameget_class_methods($class_name);
  185.             for ($i 0$i count($this->method_list[$class_name])$i++{
  186.                 $this->method_list[$class_name][$istrtolower($this->method_list[$class_name][$i]);
  187.             }
  188.         }
  189.  
  190.         //  以下のルールに従って、キャッシュが利用可能かを判定する
  191.         //  利用可能と判断した場合、キャッシュされていればそれを返す
  192.         //
  193.         //  1. メソッドに getInstance があればキャッシュを利用可能と判断する
  194.         //     この場合、シングルトンかどうかは getInstance 次第
  195.         //  2. weak が true であれば、キャッシュは利用不能と判断してオブジェクトを再生成
  196.         //  3. weak が false であれば、キャッシュは利用可能と判断する(デフォルト)
  197.         if ($this->_isCacheAvailable($class_name$this->method_list[$class_name]$weak)) {
  198.             if (isset($this->object[$key]&& is_object($this->object[$key])) {
  199.                 return $this->object[$key];
  200.             }
  201.         }
  202.  
  203.         //  インスタンス化のヘルパがあればそれを使う
  204.         $method sprintf('_getObject_%s'ucfirst($key));
  205.         if (method_exists($this$method)) {
  206.             $object $this->$method($class_name);
  207.         else if (in_array("getinstance"$this->method_list[$class_name])) {
  208.             $object call_user_func(array($class_name'getInstance'));
  209.         else {
  210.             $object new $class_name();
  211.         }
  212.  
  213.         //  クラスキーに定められたクラスのインスタンスは
  214.         //  とりあえずキャッシュする
  215.         if (isset($this->object[$key]== false || is_object($this->object[$key]== false{
  216.             $this->object[$key$object;
  217.         }
  218.  
  219.         return $object;
  220.     }
  221.  
  222.     /**
  223.      *  クラスキーに対応するクラス名を返す
  224.      *
  225.      *  @access public
  226.      *  @param  string  $key    クラスキー
  227.      *  @return string  クラス名
  228.      */
  229.     function getObjectName($key)
  230.     {
  231.         if (isset($this->class[$key]== false{
  232.             return null;
  233.         }
  234.  
  235.         return $this->class[$key];
  236.     }
  237.  
  238.     /**
  239.      *  オブジェクト生成メソッド(backend)
  240.      *
  241.      *  @access protected
  242.      *  @param  string  $class_name     クラス名
  243.      *  @return object  生成されたオブジェクト(エラーならnull) 
  244.      */
  245.     function _getObject_Backend($class_name)
  246.     {
  247.         $_ret_object new $class_name($this->ctl);
  248.         return $_ret_object;
  249.     }
  250.  
  251.     /**
  252.      *  オブジェクト生成メソッド(config)
  253.      *
  254.      *  @access protected
  255.      *  @param  string  $class_name     クラス名
  256.      *  @return object  生成されたオブジェクト(エラーならnull) 
  257.      */
  258.     function _getObject_Config($class_name)
  259.     {
  260.         $_ret_object new $class_name($this->ctl);
  261.         return $_ret_object;
  262.     }
  263.  
  264.     /**
  265.      *  オブジェクト生成メソッド(i18n)
  266.      *
  267.      *  @access protected
  268.      *  @param  string  $class_name     クラス名
  269.      *  @return object  生成されたオブジェクト(エラーならnull) 
  270.      */
  271.     function _getObject_I18n($class_name)
  272.     {
  273.         $_ret_object new $class_name($this->ctl->getDirectory('locale')$this->ctl->getAppId());
  274.         return $_ret_object;
  275.     }
  276.  
  277.     /**
  278.      *  オブジェクト生成メソッド(logger)
  279.      *
  280.      *  @access protected
  281.      *  @param  string  $class_name     クラス名
  282.      *  @return object  生成されたオブジェクト(エラーならnull) 
  283.      */
  284.     function _getObject_Logger($class_name)
  285.     {
  286.         $_ret_object new $class_name($this->ctl);
  287.         return $_ret_object;
  288.     }
  289.  
  290.     /**
  291.      *  オブジェクト生成メソッド(plugin)
  292.      *
  293.      *  @access protected
  294.      *  @param  string  $class_name     クラス名
  295.      *  @return object  生成されたオブジェクト(エラーならnull) 
  296.      */
  297.     function _getObject_Plugin($class_name)
  298.     {
  299.         $_ret_object new $class_name($this->ctl);
  300.         return $_ret_object;
  301.     }
  302.  
  303.     /**
  304.      *  オブジェクト生成メソッド(renderer)
  305.      *
  306.      *  @access protected
  307.      *  @param  string  $class_name     クラス名
  308.      *  @return object  生成されたオブジェクト(エラーならnull) 
  309.      */
  310.     function _getObject_Renderer($class_name)
  311.     {
  312.         $_ret_object new $class_name($this->ctl);
  313.         return $_ret_object;
  314.     }
  315.  
  316.     /**
  317.      *  オブジェクト生成メソッド(session)
  318.      *
  319.      *  @access protected
  320.      *  @param  string  $class_name     クラス名
  321.      *  @return object  生成されたオブジェクト(エラーならnull) 
  322.      */
  323.     function _getObject_Session($class_name)
  324.     {
  325.         $_ret_object new $class_name($this->ctl$this->ctl->getAppId());
  326.         return $_ret_object;
  327.     }
  328.  
  329.     /**
  330.      *  オブジェクト生成メソッド(sql)
  331.      *
  332.      *  @access protected
  333.      *  @param  string  $class_name     クラス名
  334.      *  @return object  生成されたオブジェクト(エラーならnull) 
  335.      */
  336.     function _getObject_Sql($class_name)
  337.     {
  338.         $_ret_object new $class_name($this->ctl);
  339.         return $_ret_object;
  340.     }
  341.  
  342.     /**
  343.      *  指定されたクラスから想定されるファイルをincludeする
  344.      *
  345.      *  @access protected
  346.      */
  347.     function _include($class_name)
  348.     {
  349.         $file sprintf("%s.%s"$class_name$this->controller->getExt('php'));
  350.         if (file_exists_ex($file)) {
  351.             include_once $file;
  352.             return true;
  353.         }
  354.  
  355.         if (preg_match('/^(\w+?)_(.*)/'$class_name$match)) {
  356.             // try ethna app style
  357.             // App_Foo_Bar_Baz -> Foo/Bar/App_Foo_Bar_Baz.php
  358.             $tmp explode("_"$match[2]);
  359.             $tmp[count($tmp)-1$class_name;
  360.             $file sprintf('%s.%s',
  361.                             implode(DIRECTORY_SEPARATOR$tmp),
  362.                             $this->controller->getExt('php'));
  363.             if (file_exists_ex($file)) {
  364.                 include_once $file;
  365.                 return true;
  366.             }
  367.  
  368.             // try ethna app & pear mixed style
  369.             // App_Foo_Bar_Baz -> Foo/Bar/Baz.php
  370.             $file sprintf('%s.%s',
  371.                             str_replace('_'DIRECTORY_SEPARATOR$match[2]),
  372.                             $this->controller->getExt('php'));
  373.             if (file_exists_ex($file)) {
  374.                 include_once $file;
  375.                 return true;
  376.             }
  377.  
  378.             // try ethna master style
  379.             // Ethna_Foo_Bar -> class/Ethna/Foo/Bar.php
  380.             $tmp explode('_'$match[2]);
  381.             array_unshift($tmp'Ethna''class');
  382.             $file sprintf('%s.%s',
  383.                             implode(DIRECTORY_SEPARATOR$tmp),
  384.                             $this->controller->getExt('php'));
  385.             if (file_exists_ex($file)) {
  386.                 include_once $file;
  387.                 return true;
  388.             }
  389.  
  390.             // try pear style
  391.             // Foo_Bar_Baz -> Foo/Bar/Baz.php
  392.             $file sprintf('%s.%s',
  393.                             str_replace('_'DIRECTORY_SEPARATOR$class_name),
  394.                             $this->controller->getExt('php'));
  395.             if (file_exists_ex($file)) {
  396.                 include_once $file;
  397.                 return true;
  398.             }
  399.         }
  400.         return false;
  401.     }
  402.  
  403.     /**
  404.      *  指定されたクラスがキャッシュを利用可能かどうかをチェックする
  405.      *
  406.      *  @access protected
  407.      */
  408.     function _isCacheAvailable($class_name$method_list$weak)
  409.     {
  410.         // if we have getInstance(), use this anyway
  411.         if (in_array('getinstance'$method_list)) {
  412.             return false;
  413.         }
  414.  
  415.         // if not, see if weak or not
  416.         return $weak false true;
  417.     }
  418. }
  419. // }}}

Documentation generated on Fri, 11 Nov 2011 03:57:45 +0900 by phpDocumentor 1.4.3