PageRenderTime 63ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/class/Controller.php

http://github.com/ethna/ethna
PHP | 1870 lines | 903 code | 211 blank | 756 comment | 158 complexity | 9b39e1312bc45ed48a65f80ac0fb7682 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. // vim: foldmethod=marker
  3. /**
  4. * Controller.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: 4337a9a9a814ce82a5698cf52650403db10ec37d $
  10. */
  11. // {{{ Ethna_Controller
  12. /**
  13. * コントローラクラス
  14. *
  15. * @author Masaki Fujimoto <fujimoto@php.net>
  16. * @access public
  17. * @package Ethna
  18. */
  19. class Ethna_Controller
  20. {
  21. /**#@+
  22. * @access protected
  23. */
  24. /** @var string $appid アプリケーションID */
  25. public $appid = 'ETHNA';
  26. /** @var string $base アプリケーションベースディレクトリ */
  27. public $base = '';
  28. /** @var string $url アプリケーションベースURL */
  29. public $url = '';
  30. /** @var string $dsn アプリケーションDSN(Data Source Name) */
  31. public $dsn;
  32. /** @var array $directory アプリケーションディレクトリ */
  33. public $directory = array();
  34. /** @var array アプリケーションディレクトリ(デフォルト) */
  35. public $directory_default = array(
  36. 'action' => 'app/action',
  37. 'action_cli' => 'app/action_cli',
  38. 'action_xmlrpc' => 'app/action_xmlrpc',
  39. 'app' => 'app',
  40. 'plugin' => 'app/plugin',
  41. 'bin' => 'bin',
  42. 'etc' => 'etc',
  43. 'filter' => 'app/filter',
  44. 'locale' => 'locale',
  45. 'log' => 'log',
  46. 'plugins' => array(),
  47. 'template' => 'template',
  48. 'template_c' => 'tmp',
  49. 'tmp' => 'tmp',
  50. 'view' => 'app/view',
  51. 'www' => 'www',
  52. 'test' => 'app/test',
  53. );
  54. /** @var array $db DBアクセス定義 */
  55. public $db = array(
  56. '' => DB_TYPE_RW,
  57. );
  58. /** @var array $ext 拡張子設定 */
  59. public $ext = array(
  60. 'php' => 'php',
  61. 'tpl' => 'tpl',
  62. );
  63. /** @var array クラス設定 */
  64. public $class = array();
  65. /** @var array $class_default クラス設定(デフォルト) */
  66. public $class_default = array(
  67. 'class' => 'Ethna_ClassFactory',
  68. 'backend' => 'Ethna_Backend',
  69. 'config' => 'Ethna_Config',
  70. 'db' => 'Ethna_DB',
  71. 'error' => 'Ethna_ActionError',
  72. 'form' => 'Ethna_ActionForm',
  73. 'i18n' => 'Ethna_I18N',
  74. 'logger' => 'Ethna_Logger',
  75. 'plugin' => 'Ethna_Plugin',
  76. 'renderer' => 'Ethna_Renderer_Smarty',
  77. 'session' => 'Ethna_Session',
  78. 'sql' => 'Ethna_AppSQL',
  79. 'view' => 'Ethna_ViewClass',
  80. 'url_handler' => 'Ethna_UrlHandler',
  81. );
  82. /** @var array subscribers */
  83. protected $subscribers = array(
  84. //"Ethna_Subscriber_I18nSubscriber",
  85. "Ethna_Subscriber_ForwardSubscriber",
  86. "Ethna_Subscriber_ResolveActionNameSubscriber",
  87. "Ethna_Subscriber_TriggerSubscriber",
  88. );
  89. /** @var array フィルタ設定 */
  90. public $filter = array(
  91. );
  92. /** @var string 使用ロケール設定 */
  93. public $locale;
  94. /** @var string システム側エンコーディング */
  95. public $system_encoding;
  96. /** @protected string クライアント側エンコーディング */
  97. /** ブラウザからのエンコーディングを指す */
  98. public $client_encoding;
  99. /** FIXME: UnitTestCase から動的に変更されるため、public */
  100. /** @protected string 現在実行中のアクション名 */
  101. public $action_name;
  102. /** @var string 現在実行中のXMLRPCメソッド名 */
  103. public $xmlrpc_method_name;
  104. /** @var array forward定義 */
  105. public $forward = array();
  106. /** @vr array デフォルトのforward定義 */
  107. public $forward_default = array(
  108. '403' => array( 'view_name' => 'Ethna_View_403',),
  109. '404' => array( 'view_name' => 'Ethna_View_404',),
  110. '500' => array( 'view_name' => 'Ethna_View_500',),
  111. 'json' => array( 'view_name' => 'Ethna_View_Json',),
  112. 'redirect' => array( 'view_name' => 'Ethna_View_Redirect',),
  113. );
  114. /** @var array action定義 */
  115. public $action = array();
  116. /** @var array action(CLI)定義 */
  117. public $action_cli = array();
  118. /** @var array action(XMLRPC)定義 */
  119. public $action_xmlrpc = array();
  120. /** @var array アプリケーションマネージャ定義 */
  121. public $manager = array();
  122. /** @var object レンダラー */
  123. public $renderer = null;
  124. /** @var array フィルターチェイン(Ethna_Filterオブジェクトの配列) */
  125. public $filter_chain = array();
  126. /** @var Ethna_ClassFactory $class_factory クラスファクトリオブジェクト */
  127. public $class_factory = null;
  128. /** @var Ethna_ActionForm $action_form フォームオブジェクト */
  129. public $action_form = null;
  130. /** @var Ethna_View $view ビューオブジェクト */
  131. public $view = null;
  132. /** @var Ethna_Config $config 設定オブジェクト */
  133. public $config = null;
  134. /** @var Ethna_Logger $logger ログオブジェクト */
  135. public $logger = null;
  136. /** @var Ethna_Plugin $plugin プラグインオブジェクト */
  137. public $plugin = null;
  138. /** @var string $gateway リクエストのゲートウェイ(www/cli/rest/xmlrpc/soap...) */
  139. public $gateway = GATEWAY_WWW;
  140. /** @var Ethna_EventDispatcher $event_dispatcher */
  141. protected $event_dispatcher;
  142. /**#@-*/
  143. /**
  144. * Ethna_Controllerクラスのコンストラクタ
  145. *
  146. * @access public
  147. */
  148. public function __construct($gateway = GATEWAY_WWW)
  149. {
  150. $this->setupEventDispatcher();
  151. $this->registerSubscriber();
  152. $GLOBALS['_Ethna_controller'] = $this;
  153. if ($this->base === "") {
  154. // EthnaコマンドなどでBASEが定義されていない場合がある
  155. if (defined('BASE')) {
  156. $this->base = BASE;
  157. }
  158. }
  159. $this->gateway = $gateway;
  160. // クラス設定の未定義値を補完
  161. foreach ($this->class_default as $key => $val) {
  162. if (isset($this->class[$key]) == false) {
  163. $this->class[$key] = $val;
  164. }
  165. }
  166. // ディレクトリ設定の未定義値を補完
  167. foreach ($this->directory_default as $key => $val) {
  168. if (isset($this->directory[$key]) == false) {
  169. $this->directory[$key] = $val;
  170. }
  171. }
  172. // クラスファクトリオブジェクトの生成
  173. $class_factory = $this->class['class'];
  174. $this->class_factory = new $class_factory($this, $this->class);
  175. // ログ管理オブジェクトの用意
  176. $this->logger = $this->getLogger();
  177. // エラーハンドラの設定
  178. Ethna::setErrorCallback(array($this, 'handleError'));
  179. // ディレクトリ名の設定(相対パス->絶対パス)
  180. foreach ($this->directory as $key => $value) {
  181. if ($key == 'plugins') {
  182. // Smartyプラグインディレクトリは配列で指定する
  183. $tmp = array();
  184. foreach (to_array($value) as $elt) {
  185. if (Ethna_Util::isAbsolute($elt) == false) {
  186. $tmp[] = $this->base . (empty($this->base) ? '' : '/') . $elt;
  187. }
  188. }
  189. $this->directory[$key] = $tmp;
  190. } else {
  191. if (Ethna_Util::isAbsolute($value) == false) {
  192. $this->directory[$key] = $this->base . (empty($this->base) ? '' : '/') . $value;
  193. }
  194. }
  195. }
  196. // 遷移先設定をマージ
  197. // 但し、キーは完全に維持する
  198. $this->forward = $this->forward + $this->forward_default;
  199. // 初期設定
  200. // フレームワークとしての内部エンコーディングはクライアント
  201. // エンコーディング(=ブラウザからのエンコーディング)
  202. //
  203. // @see Ethna_Controller#_getDefaultLanguage
  204. list($this->locale, $this->system_encoding, $this->client_encoding) = $this->_getDefaultLanguage();
  205. if (extension_loaded('mbstring')) {
  206. mb_internal_encoding($this->client_encoding);
  207. mb_regex_encoding($this->client_encoding);
  208. }
  209. $this->config = $this->getConfig();
  210. $this->dsn = $this->_prepareDSN();
  211. $this->url = $this->config->get('url');
  212. if (empty($this->url) && PHP_SAPI != 'cli') {
  213. $this->url = Ethna_Util::getUrlFromRequestUri();
  214. $this->config->set('url', $this->url);
  215. }
  216. // プラグインオブジェクトの用意
  217. $this->plugin = $this->getPlugin();
  218. $this->plugin->setLogger($this->logger);
  219. // include Ethna_Plugin_Abstract for all plugins
  220. $this->plugin->includePlugin('Abstract');
  221. // ログ出力開始
  222. $this->logger->begin();
  223. }
  224. /**
  225. * 内部イベントのsubscriberを登録する
  226. *
  227. * @return void
  228. */
  229. protected function registerSubscriber()
  230. {
  231. foreach ($this->subscribers as $subscriber_class) {
  232. $subscriber = new $subscriber_class();
  233. $this->getEventDispatcher()->addSubscriber($subscriber);
  234. }
  235. }
  236. /**
  237. * returns event dispatcher
  238. *
  239. * @return \Symfony\Component\EventDispatcher\EventDispatcher
  240. */
  241. public function getEventDispatcher()
  242. {
  243. return $this->event_dispatcher;
  244. }
  245. /**
  246. * setup Event Dispatcher
  247. */
  248. protected function setupEventDispatcher()
  249. {
  250. $this->event_dispatcher = new Ethna_EventDispatcher();
  251. }
  252. /**
  253. * アプリケーション実行後の後始末を行います。
  254. *
  255. * @access protected
  256. */
  257. public function end()
  258. {
  259. // 必要に応じてオーバライドして下さい。
  260. $this->logger->end();
  261. }
  262. /**
  263. * (現在アクティブな)コントローラのインスタンスを返す
  264. *
  265. * @access public
  266. * @return object Ethna_Controller コントローラのインスタンス
  267. * @static
  268. */
  269. public static function getInstance()
  270. {
  271. if (isset($GLOBALS['_Ethna_controller'])) {
  272. return $GLOBALS['_Ethna_controller'];
  273. } else {
  274. $_ret_object = null;
  275. return $_ret_object;
  276. }
  277. }
  278. /**
  279. * アプリケーションIDを返す
  280. *
  281. * @access public
  282. * @return string アプリケーションID
  283. */
  284. public function getAppId()
  285. {
  286. return ucfirst(strtolower($this->appid));
  287. }
  288. /**
  289. * アプリケーションIDをチェックする
  290. *
  291. * @access public
  292. * @param string $id アプリケーションID
  293. * @return mixed true:OK Ethna_Error:NG
  294. * @static
  295. */
  296. public static function checkAppId($id)
  297. {
  298. $true = true;
  299. if (strcasecmp($id, 'ethna') === 0
  300. || strcasecmp($id, 'app') === 0) {
  301. return Ethna::raiseError("Application Id [$id] is reserved\n");
  302. }
  303. // アプリケーションIDはクラス名のprefixともなるため、
  304. // 数字で始まっていてはいけない
  305. // @see http://www.php.net/manual/en/language.variables.php
  306. if (preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $id) === 0) {
  307. $msg = (preg_match('/^[0-9]$/', $id[0]))
  308. ? "Application ID must NOT start with Number.\n"
  309. : "Only Numeric(0-9) and Alphabetical(A-Z) is allowed for Application Id\n";
  310. return Ethna::raiseError($msg);
  311. }
  312. return $true;
  313. }
  314. /**
  315. * アクション名をチェックする
  316. *
  317. * @access public
  318. * @param string $action_name アクション名
  319. * @return mixed true:OK Ethna_Error:NG
  320. * @static
  321. */
  322. public static function checkActionName($action_name)
  323. {
  324. $true = true;
  325. if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
  326. $action_name) === 0) {
  327. return Ethna::raiseError("invalid action name [$action_name]");
  328. }
  329. return $true;
  330. }
  331. /**
  332. * ビュー名をチェックする
  333. *
  334. * @access public
  335. * @param string $view_name ビュー名
  336. * @return mixed true:OK Ethna_Error:NG
  337. * @static
  338. */
  339. public static function checkViewName($view_name)
  340. {
  341. $true = true;
  342. if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
  343. $view_name) === 0) {
  344. return Ethna::raiseError("invalid view name [$view_name]");
  345. }
  346. return $true;
  347. }
  348. /**
  349. * DSNを返す
  350. *
  351. * @access public
  352. * @param string $db_key DBキー
  353. * @return string DSN
  354. */
  355. public function getDSN($db_key = "")
  356. {
  357. if (isset($this->dsn[$db_key]) == false) {
  358. return null;
  359. }
  360. return $this->dsn[$db_key];
  361. }
  362. /**
  363. * DSNの持続接続設定を返す
  364. *
  365. * @access public
  366. * @param string $db_key DBキー
  367. * @return bool true:persistent false:non-persistent(あるいは設定無し)
  368. */
  369. public function getDSN_persistent($db_key = "")
  370. {
  371. $key = sprintf("dsn%s_persistent", $db_key == "" ? "" : "_$db_key");
  372. $dsn_persistent = $this->config->get($key);
  373. if (is_null($dsn_persistent)) {
  374. return false;
  375. }
  376. return $dsn_persistent;
  377. }
  378. /**
  379. * DB設定を返す
  380. *
  381. * @access public
  382. * @param string $db_key DBキー("", "r", "rw", "default", "blog_r"...)
  383. * @return string $db_keyに対応するDB種別定義(設定が無い場合はnull)
  384. */
  385. public function getDBType($db_key = null)
  386. {
  387. if (is_null($db_key)) {
  388. // 一覧を返す
  389. return $this->db;
  390. }
  391. if (isset($this->db[$db_key]) == false) {
  392. return null;
  393. }
  394. return $this->db[$db_key];
  395. }
  396. /**
  397. * アプリケーションベースURLを返す
  398. *
  399. * @access public
  400. * @return string アプリケーションベースURL
  401. */
  402. public function getURL()
  403. {
  404. return $this->url;
  405. }
  406. /**
  407. * アプリケーションベースディレクトリを返す
  408. *
  409. * @access public
  410. * @return string アプリケーションベースディレクトリ
  411. */
  412. public function getBasedir()
  413. {
  414. return $this->base;
  415. }
  416. /**
  417. * クライアントタイプ/言語からテンプレートディレクトリ名を決定する
  418. * デフォルトでは [appid]/template/ja_JP/ (ja_JPはロケール名)
  419. * ロケール名は _getDefaultLanguage で決定される。
  420. *
  421. * @access public
  422. * @return string テンプレートディレクトリ
  423. * @see Ethna_Controller#_getDefaultLanguage
  424. */
  425. public function getTemplatedir()
  426. {
  427. $template = $this->getDirectory('template');
  428. // 言語別ディレクトリ
  429. // _getDerfaultLanguageメソッドでロケールが指定されていた場合は、
  430. // テンプレートディレクトリにも自動的にそれを付加する。
  431. //if (!empty($this->locale)) {
  432. // $template .= '/' . $this->locale;
  433. //}
  434. return $template;
  435. }
  436. /**
  437. * アクションディレクトリ名を決定する
  438. *
  439. * @access public
  440. * @return string アクションディレクトリ
  441. */
  442. public function getActiondir($gateway = null)
  443. {
  444. $key = 'action';
  445. $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
  446. $result = $this->getEventDispatcher()->dispatch(Ethna_Events::CONTROLLER_GATEWAY_ACTIONDIR,
  447. new Ethna_Event_Gateway($gateway));
  448. $key = $result->getActionDirKey();
  449. return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
  450. }
  451. /**
  452. * ビューディレクトリ名を決定する
  453. *
  454. * @access public
  455. * @return string ビューディレクトリ
  456. */
  457. public function getViewdir()
  458. {
  459. return (empty($this->directory['view']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['view'] . "/"));
  460. }
  461. /**
  462. * (action,view以外の)テストケースを置くディレクトリ名を決定する
  463. *
  464. * @access public
  465. * @return string テストケースを置くディレクトリ
  466. */
  467. public function getTestdir()
  468. {
  469. return (empty($this->directory['test']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['test'] . "/"));
  470. }
  471. /**
  472. * アプリケーションディレクトリ設定を返す
  473. *
  474. * @access public
  475. * @param string $key ディレクトリタイプ("tmp", "template"...)
  476. * @return string $keyに対応したアプリケーションディレクトリ(設定が無い場合はnull)
  477. */
  478. public function getDirectory($key)
  479. {
  480. if (isset($this->directory[$key]) == false) {
  481. return null;
  482. }
  483. return $this->directory[$key];
  484. }
  485. /**
  486. * アプリケーションディレクトリ設定を返す
  487. *
  488. * @access public
  489. * @param string $key type
  490. * @return string $key directory
  491. */
  492. public function setDirectory($key, $value)
  493. {
  494. $this->directory[$key] = $value;
  495. }
  496. /**
  497. * アプリケーション拡張子設定を返す
  498. *
  499. * @access public
  500. * @param string $key 拡張子タイプ("php", "tpl"...)
  501. * @return string $keyに対応した拡張子(設定が無い場合はnull)
  502. */
  503. public function getExt($key)
  504. {
  505. if (isset($this->ext[$key]) == false) {
  506. return null;
  507. }
  508. return $this->ext[$key];
  509. }
  510. /**
  511. * クラスファクトリオブジェクトのアクセサ(R)
  512. *
  513. * @access public
  514. * @return object Ethna_ClassFactory クラスファクトリオブジェクト
  515. */
  516. public function getClassFactory()
  517. {
  518. return $this->class_factory;
  519. }
  520. /**
  521. * アクションエラーオブジェクトのアクセサ
  522. *
  523. * @access public
  524. * @return object Ethna_ActionError アクションエラーオブジェクト
  525. */
  526. public function getActionError()
  527. {
  528. return $this->class_factory->getObject('error');
  529. }
  530. /**
  531. * Accessor for ActionForm
  532. *
  533. * @access public
  534. * @return object Ethna_ActionForm アクションフォームオブジェクト
  535. */
  536. public function getActionForm()
  537. {
  538. // 明示的にクラスファクトリを利用していない
  539. return $this->action_form;
  540. }
  541. public function setActionName($action_name)
  542. {
  543. $this->action_name = $action_name;
  544. }
  545. /**
  546. * Setter for ActionForm
  547. * if the ::$action_form class is not null, then cannot set the view
  548. *
  549. * @access public
  550. * @return object Ethna_ActionForm アクションフォームオブジェクト
  551. */
  552. public function setActionForm($af)
  553. {
  554. if ($this->action_form !== null) {
  555. return false;
  556. }
  557. $this->action_form = $af;
  558. return true;
  559. }
  560. /**
  561. * Accessor for ViewClass
  562. *
  563. * @access public
  564. * @return object Ethna_View ビューオブジェクト
  565. */
  566. public function getView()
  567. {
  568. // 明示的にクラスファクトリを利用していない
  569. return $this->view;
  570. }
  571. /**
  572. * Setter for ViewClass
  573. * if the ::$view class is not null, then cannot set the view
  574. *
  575. * @access public
  576. * @param $view object Ethna_ViewClass
  577. * @return boolean
  578. */
  579. public function setView($view)
  580. {
  581. if ($this->view !== null) {
  582. return false;
  583. }
  584. $this->view = $view;
  585. return true;
  586. }
  587. /**
  588. * backendオブジェクトのアクセサ
  589. *
  590. * @access public
  591. * @return object Ethna_Backend backendオブジェクト
  592. */
  593. public function getBackend()
  594. {
  595. return $this->class_factory->getObject('backend');
  596. }
  597. /**
  598. * 設定オブジェクトのアクセサ
  599. *
  600. * @access public
  601. * @return object Ethna_Config 設定オブジェクト
  602. */
  603. public function getConfig()
  604. {
  605. return $this->class_factory->getObject('config');
  606. }
  607. /**
  608. * i18nオブジェクトのアクセサ(R)
  609. *
  610. * @access public
  611. * @return object Ethna_I18N i18nオブジェクト
  612. */
  613. public function getI18N()
  614. {
  615. return $this->class_factory->getObject('i18n');
  616. }
  617. /**
  618. * ログオブジェクトのアクセサ
  619. *
  620. * @access public
  621. * @return object Ethna_Logger ログオブジェクト
  622. */
  623. public function getLogger()
  624. {
  625. return $this->class_factory->getObject('logger');
  626. }
  627. /**
  628. * セッションオブジェクトのアクセサ
  629. *
  630. * @access public
  631. * @return object Ethna_Session セッションオブジェクト
  632. */
  633. public function getSession()
  634. {
  635. return $this->class_factory->getObject('session');
  636. }
  637. /**
  638. * SQLオブジェクトのアクセサ
  639. *
  640. * @access public
  641. * @return object Ethna_AppSQL SQLオブジェクト
  642. */
  643. public function getSQL()
  644. {
  645. return $this->class_factory->getObject('sql');
  646. }
  647. /**
  648. * プラグインオブジェクトのアクセサ
  649. *
  650. * @access public
  651. * @return object Ethna_Plugin プラグインオブジェクト
  652. */
  653. public function getPlugin()
  654. {
  655. return $this->class_factory->getObject('plugin');
  656. }
  657. /**
  658. * URLハンドラオブジェクトのアクセサ
  659. *
  660. * @access public
  661. * @return object Ethna_UrlHandler URLハンドラオブジェクト
  662. */
  663. public function getUrlHandler()
  664. {
  665. return $this->class_factory->getObject('url_handler');
  666. }
  667. /**
  668. * マネージャ一覧を返す
  669. *
  670. * @access public
  671. * @return array マネージャ一覧
  672. * @obsolete
  673. */
  674. public function getManagerList()
  675. {
  676. return $this->manager;
  677. }
  678. /**
  679. * 実行中のアクション名を返す
  680. *
  681. * @access public
  682. * @return string 実行中のアクション名
  683. */
  684. public function getCurrentActionName()
  685. {
  686. return $this->action_name;
  687. }
  688. /**
  689. * 実行中のXMLRPCメソッド名を返す
  690. *
  691. * @access public
  692. * @return string 実行中のXMLRPCメソッド名
  693. */
  694. public function getXmlrpcMethodName()
  695. {
  696. return $this->xmlrpc_method_name;
  697. }
  698. /**
  699. * ロケール設定、使用言語を取得する
  700. *
  701. * @access public
  702. * @return array ロケール名(e.x ja_JP, en_US 等),
  703. * システムエンコーディング名,
  704. * クライアントエンコーディング名 の配列
  705. * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
  706. * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
  707. */
  708. public function getLanguage()
  709. {
  710. return array($this->locale, $this->system_encoding, $this->client_encoding);
  711. }
  712. /**
  713. * ロケール名へのアクセサ(R)
  714. *
  715. * @access public
  716. * @return string ロケール名(e.x ja_JP, en_US 等),
  717. * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
  718. */
  719. public function getLocale()
  720. {
  721. return $this->locale;
  722. }
  723. /**
  724. * ロケール名へのアクセサ(W)
  725. *
  726. * @access public
  727. * @param $locale ロケール名(e.x ja_JP, en_US 等),
  728. * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
  729. */
  730. public function setLocale($locale)
  731. {
  732. $this->locale = $locale;
  733. $this->getEventDispatcher()->dispatch("ethna.core.language",
  734. new Ethna_Event_SetLanguage($this,
  735. $this->getLocale(),
  736. $this->getSystemEncoding(),
  737. $this->getClientEncoding()
  738. ));
  739. }
  740. /**
  741. * クライアントエンコーディング名へのアクセサ(R)
  742. *
  743. * @access public
  744. * @return string $client_encoding クライアントエンコーディング名
  745. */
  746. public function getClientEncoding()
  747. {
  748. return $this->client_encoding;
  749. }
  750. /**
  751. * クライアントエンコーディング名へのアクセサ(W)
  752. *
  753. * @access public
  754. * @param string $client_encoding クライアントエンコーディング名
  755. */
  756. public function setClientEncoding($client_encoding)
  757. {
  758. $this->client_encoding = $client_encoding;
  759. $this->getEventDispatcher()->dispatch("ethna.core.language",
  760. new Ethna_Event_SetLanguage($this,
  761. $this->getLocale(),
  762. $this->getSystemEncoding(),
  763. $this->getClientEncoding()
  764. ));
  765. }
  766. /**
  767. * ゲートウェイを取得する
  768. *
  769. * @access public
  770. */
  771. public function getGateway()
  772. {
  773. return $this->gateway;
  774. }
  775. /**
  776. * ゲートウェイモードを設定する
  777. *
  778. * @access public
  779. */
  780. public function setGateway($gateway)
  781. {
  782. $this->gateway = $gateway;
  783. }
  784. /**
  785. * アプリケーションのエントリポイント
  786. *
  787. * @access public
  788. * @param string $class_name アプリケーションコントローラのクラス名
  789. * @param mixed $action_name 指定のアクション名(省略可)
  790. * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
  791. * @static
  792. */
  793. public static function main($class_name, $action_name = "", $fallback_action_name = "")
  794. {
  795. $c = new $class_name;
  796. $c->trigger($action_name, $fallback_action_name);
  797. $c->end();
  798. }
  799. /**
  800. * CLIアプリケーションのエントリポイント
  801. *
  802. * @access public
  803. * @param string $class_name アプリケーションコントローラのクラス名
  804. * @param string $action_name 実行するアクション名
  805. * @param bool $enable_filter フィルタチェインを有効にするかどうか
  806. * @static
  807. */
  808. public static function main_CLI($class_name, $action_name, $enable_filter = true)
  809. {
  810. $c = new $class_name(GATEWAY_CLI);
  811. $c->action_cli[$action_name] = array();
  812. $c->trigger($action_name, "", $enable_filter);
  813. $c->end();
  814. }
  815. /**
  816. * SOAPアプリケーションのエントリポイント
  817. *
  818. * @access public
  819. * @param string $class_name アプリケーションコントローラのクラス名
  820. * @param mixed $action_name 指定のアクション名(省略可)
  821. * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
  822. * @static
  823. */
  824. public static function main_SOAP($class_name, $action_name = "", $fallback_action_name = "")
  825. {
  826. $c = new $class_name(GATEWAY_SOAP);
  827. $c->trigger($action_name, $fallback_action_name);
  828. $c->end();
  829. }
  830. protected function executePreTriggerFilter()
  831. {
  832. // 実行前フィルタ
  833. for ($i = 0; $i < count($this->filter_chain); $i++) {
  834. $r = $this->filter_chain[$i]->preFilter();
  835. if (Ethna::isError($r)) {
  836. return $r;
  837. }
  838. }
  839. }
  840. protected function executePostTriggerFilter()
  841. {
  842. // 実行後フィルタ
  843. for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
  844. $r = $this->filter_chain[$i]->postFilter();
  845. if (Ethna::isError($r)) {
  846. return $r;
  847. }
  848. }
  849. }
  850. /**
  851. * フレームワークの処理を開始する
  852. *
  853. * @access public
  854. * @param mixed $default_action_name 指定のアクション名
  855. * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
  856. * @param bool $enable_filter フィルタチェインを有効にするかどうか
  857. * @return mixed 0:正常終了 Ethna_Error:エラー
  858. */
  859. public function trigger($default_action_name = "", $fallback_action_name = "", $enable_filter = true)
  860. {
  861. // フィルターの生成
  862. if ($enable_filter) {
  863. $this->_createFilterChain();
  864. }
  865. if (Ethna::isError($error = $this->executePreTriggerFilter())) {
  866. // TODO(chobie): これ普通に考えてErrorで落としたらサダメだよね
  867. return $error;
  868. }
  869. // trigger
  870. $this->getEventDispatcher()->dispatch(Ethna_Events::CONTROLLER_TRIGGER,
  871. new Ethna_Event_Trigger($this, $default_action_name, $fallback_action_name, $this->getGateway()));
  872. $this->executePostTriggerFilter();
  873. }
  874. /**
  875. * pre action filterを実行する
  876. *
  877. * @param $action_name
  878. * @return mixed
  879. */
  880. public function executePreActionFilter(&$action_name)
  881. {
  882. for ($i = 0; $i < count($this->filter_chain); $i++) {
  883. $r = $this->filter_chain[$i]->preActionFilter($action_name);
  884. if ($r != null) {
  885. $this->logger->log(LOG_DEBUG, 'action [%s] -> [%s] by %s', $action_name, $r, get_class($this->filter_chain[$i]));
  886. $action_name = $r;
  887. }
  888. }
  889. return $action_name;
  890. }
  891. /**
  892. * post action filterを実行する
  893. *
  894. * @param $forward_name
  895. * @param $action_name
  896. */
  897. public function executePostActionFilter(&$forward_name, $action_name)
  898. {
  899. // アクション実行後フィルタ
  900. for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
  901. $r = $this->filter_chain[$i]->postActionFilter($action_name, $forward_name);
  902. if ($r != null) {
  903. $this->logger->log(LOG_DEBUG, 'forward [%s] -> [%s] by %s', $forward_name, $r, get_class($this->filter_chain[$i]));
  904. $forward_name = $r;
  905. }
  906. }
  907. }
  908. public function verifyActionObject(&$action_obj, &$action_name, $fallback_action_name)
  909. {
  910. if (is_null($action_obj)) {
  911. if ($fallback_action_name != "") {
  912. $this->logger->log(LOG_DEBUG, 'undefined action [%s] -> try fallback action [%s]', $action_name, $fallback_action_name);
  913. $action_obj = $this->_getAction($fallback_action_name);
  914. }
  915. if (is_null($action_obj)) {
  916. return Ethna::raiseError("undefined action [%s]", E_APP_UNDEFINED_ACTION, $action_name);
  917. } else {
  918. $action_name = $fallback_action_name;
  919. }
  920. }
  921. return;
  922. }
  923. /**
  924. * action formを設定する
  925. *
  926. * @param $action_name
  927. */
  928. public function setupActionForm($action_name)
  929. {
  930. $form_name = $this->getActionFormName($action_name);
  931. $this->action_form = new $form_name($this);
  932. $this->getBackend()->setActionForm($this->action_form);
  933. $this->action_form->setFormDef_PreHelper();
  934. $this->action_form->setFormVars();
  935. }
  936. /**
  937. * エラーハンドラ
  938. *
  939. * エラー発生時の追加処理を行いたい場合はこのメソッドをオーバーライドする
  940. * (アラートメール送信等−デフォルトではログ出力時にアラートメール
  941. * が送信されるが、エラー発生時に別にアラートメールをここで送信
  942. * させることも可能)
  943. *
  944. * @access public
  945. * @param object Ethna_Error エラーオブジェクト
  946. */
  947. public function handleError($error)
  948. {
  949. // ログ出力
  950. list ($log_level, $dummy) = $this->logger->errorLevelToLogLevel($error->getLevel());
  951. $message = $error->getMessage();
  952. $this->logger->log($log_level, sprintf("%s [ERROR CODE(%d)]", $message, $error->getCode()));
  953. }
  954. /**
  955. * エラーメッセージを取得する
  956. *
  957. * @access public
  958. * @param int $code エラーコード
  959. * @return string エラーメッセージ
  960. */
  961. public function getErrorMessage($code)
  962. {
  963. $message_list = $GLOBALS['_Ethna_error_message_list'];
  964. for ($i = count($message_list)-1; $i >= 0; $i--) {
  965. if (array_key_exists($code, $message_list[$i])) {
  966. return $message_list[$i][$code];
  967. }
  968. }
  969. return null;
  970. }
  971. /**
  972. * 実行するアクション名を返す
  973. *
  974. * @access protected
  975. * @param mixed $default_action_name 指定のアクション名
  976. * @return string 実行するアクション名
  977. */
  978. public function _getActionName($default_action_name, $fallback_action_name)
  979. {
  980. // フォームから要求されたアクション名を取得する
  981. $event = $this->getEventDispatcher()->dispatch(Ethna_Events::CONTROLLER_RESOLVE_ACTION,
  982. new Ethna_Event_ResolveActionName($this, $default_action_name, $fallback_action_name));
  983. $action_name = $event->getActionName();
  984. $this->logger->log(LOG_DEBUG, '<<< action_name[%s] >>>', $action_name);
  985. return $action_name;
  986. }
  987. /**
  988. * アクション名を指定するクエリ/HTMLを生成する
  989. *
  990. * @access public
  991. * @param string $action action to request
  992. * @param string $type hidden, url...
  993. * @todo consider gateway
  994. */
  995. public function getActionRequest($action, $type = "hidden")
  996. {
  997. $s = null;
  998. if ($type == "hidden") {
  999. $s = sprintf('<input type="hidden" name="action_%s" value="true" />', htmlspecialchars($action, ENT_QUOTES, $this->getClientEncoding()));
  1000. } else if ($type == "url") {
  1001. $s = sprintf('action_%s=true', urlencode($action));
  1002. }
  1003. return $s;
  1004. }
  1005. /**
  1006. * フォームにより要求されたアクション名に対応する定義を返す
  1007. *
  1008. * @access private
  1009. * @param string $action_name アクション名
  1010. * @return array アクション定義
  1011. */
  1012. public function _getAction($action_name, $gateway = null)
  1013. {
  1014. $action = array();
  1015. $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
  1016. $result = $this->getEventDispatcher()->dispatch(Ethna_Events::CONTROLLER_GATEWAY_ACTIONDIR,
  1017. new Ethna_Event_Gateway($gateway));
  1018. $target = $result->getActionDirKey();
  1019. $action = $this->$target;
  1020. $action_obj = array();
  1021. if (isset($action[$action_name])) {
  1022. $action_obj = $action[$action_name];
  1023. if (isset($action_obj['inspect']) && $action_obj['inspect']) {
  1024. return $action_obj;
  1025. }
  1026. } else {
  1027. $this->logger->log(LOG_DEBUG, "action [%s] is not defined -> try default", $action_name);
  1028. }
  1029. // アクションスクリプトのインクルード
  1030. $this->_includeActionScript($action_obj, $action_name);
  1031. // 省略値の補正
  1032. if (isset($action_obj['class_name']) == false) {
  1033. $action_obj['class_name'] = $this->getDefaultActionClass($action_name);
  1034. }
  1035. if (isset($action_obj['form_name']) == false) {
  1036. $action_obj['form_name'] = $this->getDefaultFormClass($action_name);
  1037. } else if (class_exists($action_obj['form_name']) == false) {
  1038. // 明示指定されたフォームクラスが定義されていない場合は警告
  1039. $this->logger->log(LOG_WARNING, 'stated form class is not defined [%s]', $action_obj['form_name']);
  1040. }
  1041. // 必要条件の確認
  1042. if (class_exists($action_obj['class_name']) == false) {
  1043. $this->logger->log(LOG_NOTICE, 'action class is not defined [%s]', $action_obj['class_name']);
  1044. $_ret_object = null;
  1045. return $_ret_object;
  1046. }
  1047. if (class_exists($action_obj['form_name']) == false) {
  1048. // フォームクラスは未定義でも良い
  1049. $class_name = $this->class_factory->getObjectName('form');
  1050. $this->logger->log(LOG_DEBUG, 'form class is not defined [%s] -> falling back to default [%s]', $action_obj['form_name'], $class_name);
  1051. $action_obj['form_name'] = $class_name;
  1052. }
  1053. $action_obj['inspect'] = true;
  1054. $action[$action_name] = $action_obj;
  1055. return $action[$action_name];
  1056. }
  1057. /**
  1058. * アクション名とアクションクラスからの戻り値に基づいて遷移先を決定する
  1059. *
  1060. * @access protected
  1061. * @param string $action_name アクション名
  1062. * @param string $retval アクションクラスからの戻り値
  1063. * @return string 遷移先
  1064. */
  1065. public function _sortForward($action_name, $retval)
  1066. {
  1067. return $retval;
  1068. }
  1069. /**
  1070. * フィルタチェインを生成する
  1071. *
  1072. * @access protected
  1073. */
  1074. public function _createFilterChain()
  1075. {
  1076. $this->filter_chain = array();
  1077. foreach ($this->filter as $filter) {
  1078. $filter_plugin = $this->plugin->getPlugin('Filter', $filter);
  1079. if (Ethna::isError($filter_plugin)) {
  1080. continue;
  1081. }
  1082. $this->filter_chain[] = $filter_plugin;
  1083. }
  1084. }
  1085. /**
  1086. * アクション名が実行許可されているものかどうかを返す
  1087. *
  1088. * @access private
  1089. * @param string $action_name リクエストされたアクション名
  1090. * @param array $default_action_name 許可されているアクション名
  1091. * @return bool true:許可 false:不許可
  1092. */
  1093. public function _isAcceptableActionName($action_name, $default_action_name)
  1094. {
  1095. foreach (to_array($default_action_name) as $name) {
  1096. if ($action_name == $name) {
  1097. return true;
  1098. } else if ($name{strlen($name)-1} == '*') {
  1099. if (strncmp($action_name, substr($name, 0, -1), strlen($name)-1) == 0) {
  1100. return true;
  1101. }
  1102. }
  1103. }
  1104. return false;
  1105. }
  1106. /**
  1107. * 指定されたアクションのフォームクラス名を返す(オブジェクトの生成は行わない)
  1108. *
  1109. * @access public
  1110. * @param string $action_name アクション名
  1111. * @return string アクションのフォームクラス名
  1112. */
  1113. public function getActionFormName($action_name)
  1114. {
  1115. $action_obj = $this->_getAction($action_name);
  1116. if (is_null($action_obj)) {
  1117. return null;
  1118. }
  1119. return $action_obj['form_name'];
  1120. }
  1121. /**
  1122. * アクションに対応するフォームクラス名が省略された場合のデフォルトクラス名を返す
  1123. *
  1124. * デフォルトでは[プロジェクトID]_Form_[アクション名]となるので好み応じてオーバライドする
  1125. *
  1126. * @access public
  1127. * @param string $action_name アクション名
  1128. * @return string アクションフォーム名
  1129. */
  1130. public function getDefaultFormClass($action_name, $gateway = null)
  1131. {
  1132. $gateway_prefix = $this->_getGatewayPrefix($gateway);
  1133. $postfix = preg_replace_callback('/_(.)/', function(array $matches){return strtoupper($matches[1]);}, ucfirst($action_name));
  1134. $r = sprintf("%s_%sForm_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
  1135. $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
  1136. return $r;
  1137. }
  1138. /**
  1139. * getDefaultFormClass()で取得したクラス名からアクション名を取得する
  1140. *
  1141. * getDefaultFormClass()をオーバーライドした場合、こちらも合わせてオーバーライド
  1142. * することを推奨(必須ではない)
  1143. *
  1144. * @access public
  1145. * @param string $class_name フォームクラス名
  1146. * @return string アクション名
  1147. */
  1148. public function actionFormToName($class_name)
  1149. {
  1150. $prefix = sprintf("%s_Form_", $this->getAppId());
  1151. if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
  1152. // 不明なクラス名
  1153. return null;
  1154. }
  1155. $target = $match[1];
  1156. $action_name = substr(preg_replace_callback('/([A-Z])/', function(array $matches){return strtolower($matches[1]);}, $target), 1);
  1157. return $action_name;
  1158. }
  1159. /**
  1160. * アクションに対応するフォームパス名が省略された場合のデフォルトパス名を返す
  1161. *
  1162. * デフォルトでは_getDefaultActionPath()と同じ結果を返す(1ファイルに
  1163. * アクションクラスとフォームクラスが記述される)ので、好みに応じて
  1164. * オーバーライドする
  1165. *
  1166. * @access public
  1167. * @param string $action_name アクション名
  1168. * @return string form classが定義されるスクリプトのパス名
  1169. */
  1170. public function getDefaultFormPath($action_name)
  1171. {
  1172. return $this->getDefaultActionPath($action_name);
  1173. }
  1174. /**
  1175. * 指定されたアクションのクラス名を返す(オブジェクトの生成は行わない)
  1176. *
  1177. * @access public
  1178. * @param string $action_name アクションの名称
  1179. * @return string アクションのクラス名
  1180. */
  1181. public function getActionClassName($action_name)
  1182. {
  1183. $action_obj = $this->_getAction($action_name);
  1184. if ($action_obj == null) {
  1185. return null;
  1186. }
  1187. return $action_obj['class_name'];
  1188. }
  1189. /**
  1190. * アクションに対応するアクションクラス名が省略された場合のデフォルトクラス名を返す
  1191. *
  1192. * デフォルトでは[プロジェクトID]_Action_[アクション名]となるので好み応じてオーバライドする
  1193. *
  1194. * @access public
  1195. * @param string $action_name アクション名
  1196. * @return string アクションクラス名
  1197. */
  1198. public function getDefaultActionClass($action_name, $gateway = null)
  1199. {
  1200. $gateway_prefix = $this->_getGatewayPrefix($gateway);
  1201. $postfix = preg_replace_callback('/_(.)/', function(array $matches){return strtoupper($matches[1]);}, ucfirst($action_name));
  1202. $r = sprintf("%s_%sAction_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
  1203. $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
  1204. return $r;
  1205. }
  1206. /**
  1207. * getDefaultActionClass()で取得したクラス名からアクション名を取得する
  1208. *
  1209. * getDefaultActionClass()をオーバーライドした場合、こちらも合わせてオーバーライド
  1210. * することを推奨(必須ではない)
  1211. *
  1212. * @access public
  1213. * @param string $class_name アクションクラス名
  1214. * @return string アクション名
  1215. */
  1216. public function actionClassToName($class_name)
  1217. {
  1218. $prefix = sprintf("%s_Action_", $this->getAppId());
  1219. if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
  1220. // 不明なクラス名
  1221. return null;
  1222. }
  1223. $target = $match[1];
  1224. $action_name = substr(preg_replace_callback('/([A-Z])/', function(array $matches){return '_' . strtolower($matches[1]);} , $target), 1);
  1225. return $action_name;
  1226. }
  1227. /**
  1228. * アクションに対応するアクションパス名が省略された場合のデフォルトパス名を返す
  1229. *
  1230. * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
  1231. *
  1232. * @access public
  1233. * @param string $action_name アクション名
  1234. * @return string アクションクラスが定義されるスクリプトのパス名
  1235. */
  1236. public function getDefaultActionPath($action_name)
  1237. {
  1238. $r = preg_replace_callback('/_(.)/', function(array $matches){return '/' . strtoupper($matches[1]);}, ucfirst($action_name)) . '.' . $this->getExt('php');
  1239. $this->logger->log(LOG_DEBUG, "default action path [%s]", $r);
  1240. return $r;
  1241. }
  1242. /**
  1243. * 指定された遷移名に対応するビュークラス名を返す(オブジェクトの生成は行わない)
  1244. *
  1245. * @access public
  1246. * @param string $forward_name 遷移先の名称
  1247. * @return string view classのクラス名
  1248. */
  1249. public function getViewClassName($forward_name)
  1250. {
  1251. if ($forward_name == null) {
  1252. return null;
  1253. }
  1254. if (isset($this->forward[$forward_name])) {
  1255. $forward_obj = $this->forward[$forward_name];
  1256. } else {
  1257. $forward_obj = array();
  1258. }
  1259. if (isset($forward_obj['view_name'])) {
  1260. $class_name = $forward_obj['view_name'];
  1261. if (class_exists($class_name)) {
  1262. return $class_name;
  1263. }
  1264. } else {
  1265. $class_name = null;
  1266. }
  1267. // viewのインクルード
  1268. $this->_includeViewScript($forward_obj, $forward_name);
  1269. if (is_null($class_name) == false && class_exists($class_name)) {
  1270. return $class_name;
  1271. } else if (is_null($class_name) == false) {
  1272. $this->logger->log(LOG_WARNING, 'stated view class is not defined [%s] -> try default', $class_name);
  1273. }
  1274. $class_name = $this->getDefaultViewClass($forward_name);
  1275. if (class_exists($class_name)) {
  1276. return $class_name;
  1277. } else {
  1278. $class_name = $this->class_factory->getObjectName('view');
  1279. $this->logger->log(LOG_DEBUG, 'view class is not defined for [%s] -> use default [%s]', $forward_name, $class_name);
  1280. return $class_name;
  1281. }
  1282. }
  1283. /**
  1284. * 遷移名に対応するビュークラス名が省略された場合のデフォルトクラス名を返す
  1285. *
  1286. * デフォルトでは[プロジェクトID]_View_[遷移名]となるので好み応じてオーバライドする
  1287. *
  1288. * @access public
  1289. * @param string $forward_name forward名
  1290. * @return string view classクラス名
  1291. */
  1292. public function getDefaultViewClass($forward_name, $gateway = null)
  1293. {
  1294. $gateway_prefix = $this->_getGatewayPrefix($gateway);
  1295. $postfix = preg_replace_callback('/_(.)/', function(array $matches){return strtoupper($matches[1]);}, ucfirst($forward_name));
  1296. $r = sprintf("%s_%sView_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
  1297. $this->logger->log(LOG_DEBUG, "default view class [%s]", $r);
  1298. return $r;
  1299. }
  1300. /**
  1301. * 遷移名に対応するビューパス名が省略された場合のデフォルトパス名を返す
  1302. *
  1303. * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
  1304. *
  1305. * @access public
  1306. * @param string $forward_name forward名
  1307. * @return string view classが定義されるスクリプトのパス名
  1308. */
  1309. public function getDefaultViewPath($forward_name)
  1310. {
  1311. $r = preg_replace_callback('/_(.)/', function(array $matches){return '/' . strtoupper($matches[1]); }, ucfirst($forward_name)) . '.' . $this->getExt('php');
  1312. $this->logger->log(LOG_DEBUG, "default view path [%s]", $r);
  1313. return $r;
  1314. }
  1315. /**
  1316. * 遷移名に対応するテンプレートパス名が省略された場合のデフォルトパス名を返す
  1317. *
  1318. * デフォルトでは"foo_bar"というforward名が"foo/bar" + テンプレート拡張子となる
  1319. * ので好み応じてオーバライドする
  1320. *
  1321. * @access public
  1322. * @param string $forward_name forward名
  1323. * @return string forwardパス名
  1324. */
  1325. public function getDefaultForwardPath($forward_name)
  1326. {
  1327. return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl'];
  1328. }
  1329. /**
  1330. * テンプレートパス名から遷移名を取得する
  1331. *
  1332. * getDefaultForwardPath()をオーバーライドした場合、こちらも合わせてオーバーライド
  1333. * することを推奨(必須ではない)
  1334. *
  1335. * @access public
  1336. * @param string $forward_path テンプレートパス名
  1337. * @return string 遷移名
  1338. */
  1339. public function forwardPathToName($forward_path)
  1340. {
  1341. $forward_path = preg_replace('/^\/+/', '', $forward_path);
  1342. $forward_path = preg_replace(sprintf('/\.%s$/', $this->getExt('tpl')), '', $forward_path);
  1343. return str_replace('/', '_', $forward_path);
  1344. }
  1345. /**
  1346. * 遷移名からテンプレートファイルのパス名を取得する
  1347. *
  1348. * @access private

Large files files are truncated, but you can click here to view the full file