/**
  * RESTする
  * @return array 配列構造のリソースデータ
  */
 public function execute($argResourceHint = NULL, $argRequestParams = NULL)
 {
     static $prepend = FALSE;
     static $append = FALSE;
     $this->_init();
     debug($this->restResource);
     // RESTアクセスされるリソースの特定
     $this->restResource = $argResourceHint;
     if (NULL === $argResourceHint) {
         $this->restResource = $_GET['_r_'];
     }
     if (isset($_GET['_deep_']) && TRUE == ('0' === $_GET['_deep_'] || 'false' === strtolower($_GET['_deep_']))) {
         // RESTのDEEPモードを無効にする
         // XXX DEEPモードがTRUEの場合、[model名]_idのフィールドがリソースに合った場合、そのリソースまで自動で参照・更新・作成を試みます
         $this->deepRESTMode = FALSE;
     }
     if (isset($_SERVER['REQUEST_METHOD'])) {
         $this->requestMethod = strtoupper($_SERVER['REQUEST_METHOD']);
         if (isset($_POST['_method_']) && strlen($_POST['_method_']) > 0) {
             $this->requestMethod = strtoupper($_POST['_method_']);
         }
     }
     debug($this->restResource);
     debug('rest method=' . strtolower($this->requestMethod));
     $resource = self::resolveRESTResource($this->restResource);
     debug($resource);
     if (NULL === $resource) {
         // リソースの指定が無かったのでエラー終了
         $this->httpStatus = 400;
         throw new RESTException(__CLASS__ . PATH_SEPARATOR . __METHOD__ . PATH_SEPARATOR . __LINE__, 400);
     }
     if ('GET' !== $this->requestMethod && 'HEAD' !== $this->requestMethod && 'POST' !== $this->requestMethod && NULL === $resource['ids']) {
         // GET,POST以外のメソッドの場合はリソースID指定は必須
         $this->httpStatus = 400;
         throw new RESTException(__CLASS__ . PATH_SEPARATOR . __METHOD__ . PATH_SEPARATOR . __LINE__, 400);
     }
     $res = FALSE;
     $DBO = NULL;
     try {
         $DBO = self::_getDBO();
         // RESTの実行
         $this->restResourceModel = $resource['model'];
         if (NULL === $this->restResourceListed) {
             $this->restResourceListed = $resource['listed'];
         }
         $this->restResource = $resource;
         // Prepend処理
         if (TRUE === $this->rootREST && FALSE === $prepend) {
             $prepend = TRUE;
             // Filterがあったらフィルター処理をする
             $filerName = 'RestPrependFilter';
             debug('$filerName=' . $filerName);
             if (FALSE !== MVCCore::loadMVCFilter($filerName, TRUE)) {
                 $filterClass = MVCCore::loadMVCFilter($filerName);
                 $Filter = new $filterClass();
                 $Filter->REST = $this;
                 $Filter->execute($argRequestParams);
             }
         }
         $classHint = str_replace(' ', '', ucwords(str_replace(' ', '', $this->restResourceModel)));
         debug('$classHint=' . $classHint);
         if (FALSE !== MVCCore::loadMVCModule($classHint, TRUE)) {
             debug('RestClassLoaded');
             // オーバーライドされたModelへのリソース操作クラスが在る場合は、それをnewして実行する
             $className = MVCCore::loadMVCModule($classHint);
             $RestController = new $className();
             // 自分自身の持っているパブリックパラメータをブリッジ先のRestControllerに引き渡す
             $RestController->controlerClassName = $this->restResourceModel;
             $RestController->httpStatus = $this->httpStatus;
             $RestController->outputType = $this->outputType;
             $RestController->requestMethod = $this->requestMethod;
             $RestController->restResource = $this->restResource;
             $RestController->jsonUnescapedUnicode = $this->jsonUnescapedUnicode;
             $RestController->deviceType = $this->deviceType;
             $RestController->appVersion = $this->appVersion;
             $RestController->appleReviewd = $this->appleReviewd;
             $RestController->mustAppVersioned = $this->mustAppVersioned;
             $RestController->deepRESTMode = $this->deepRESTMode;
             $RestController->restResource = $this->restResource;
             $RestController->restResourceModel = $this->restResourceModel;
             $RestController->restResourceListed = $this->restResourceListed;
             $RestController->restResourceCreateDateKeyName = $this->restResourceCreateDateKeyName;
             $RestController->restResourceModifyDateKeyName = $this->restResourceModifyDateKeyName;
             $RestController->AuthUser = $this->AuthUser;
             $RestController->authUserID = $this->authUserID;
             $RestController->authUserIDFieldName = $this->authUserIDFieldName;
             $RestController->authUserQuery = $this->authUserQuery;
             // リクエストメソッドで分岐する
             if ('POST' === $this->requestMethod || 'PUT' === $this->requestMethod) {
                 $res = $RestController->{strtolower($this->requestMethod)}($argRequestParams);
             } else {
                 $res = $RestController->{strtolower($this->requestMethod)}();
             }
             // 結果のパラメータを受け取り直す
             $this->httpStatus = $RestController->httpStatus;
             $this->outputType = $RestController->outputType;
             $this->requestMethod = $RestController->requestMethod;
             $this->restResource = $RestController->restResource;
             $this->jsonUnescapedUnicode = $RestController->jsonUnescapedUnicode;
             $this->deviceType = $RestController->deviceType;
             $this->appVersion = $RestController->appVersion;
             $this->appleReviewd = $RestController->appleReviewd;
             $this->mustAppVersioned = $RestController->mustAppVersioned;
             $this->deepRESTMode = $RestController->deepRESTMode;
             $this->restResource = $RestController->restResource;
             $this->restResourceModel = $RestController->restResourceModel;
             $this->restResourceListed = $RestController->restResourceListed;
             $this->restResourceCreateDateKeyName = $RestController->restResourceCreateDateKeyName;
             $this->restResourceModifyDateKeyName = $RestController->restResourceModifyDateKeyName;
             $this->AuthUser = $RestController->AuthUser;
             $this->authUserID = $RestController->authUserID;
             $this->authUserIDFieldName = $RestController->authUserIDFieldName;
             $this->authUserQuery = $RestController->authUserQuery;
         } else {
             // リクエストメソッドで分岐する
             $res = $this->{strtolower($this->requestMethod)}();
         }
         // Append処理
         if (TRUE === $this->rootREST && FALSE === $append) {
             $append = TRUE;
             // Filterがあったらフィルター処理をする
             $filerName = 'RestAppendFilter';
             debug('$filerName=' . $filerName);
             if (FALSE !== MVCCore::loadMVCFilter($filerName, TRUE)) {
                 $filterClass = MVCCore::loadMVCFilter($filerName);
                 $Filter = new $filterClass();
                 $Filter->REST = $this;
                 $Filter->execute($argRequestParams);
             }
         }
         // トランザクションを正常終了する
         $DBO->commit();
     } catch (Exception $Exception) {
         if (NULL !== $DBO && is_object($DBO)) {
             // トランザクションを異常終了する
             $DBO->rollback();
         }
         // 実装の問題によるエラー
         $this->httpStatus = 500;
         if (400 === $Exception->getCode() || 401 === $Exception->getCode() || 404 === $Exception->getCode() || 405 === $Exception->getCode() || 503 === $Exception->getCode()) {
             $this->httpStatus = $Exception->getCode();
         }
         throw new RESTException($Exception->getMessage(), $this->httpStatus);
     }
     debug('res=');
     debug($res);
     if (TRUE === $res) {
         $res = array('success' => TRUE);
     }
     if (FALSE === $res || TRUE !== is_array($res)) {
         // XXX ココを通るのは相当なイレギュラー!
         // 恐らく実装の問題
         $this->httpStatus = 500;
         throw new RESTException(__CLASS__ . PATH_SEPARATOR . __METHOD__ . PATH_SEPARATOR . __LINE__, 400);
     }
     if (TRUE === is_array($res) && 'HEAD' !== $this->requestMethod) {
         if ('html' === $this->outputType) {
             debug('convert html');
             $basehtml = '';
             $URIs = explode('?', $_SERVER['REQUEST_URI']);
             if ("index" === strtolower($this->restResourceModel)) {
                 $basehtml .= '<h2>Table List</h2>' . PHP_EOL;
                 $basehtml .= '<ul>' . PHP_EOL;
                 for ($idx = 0; $idx < count($res); $idx++) {
                     $basehtml .= '<li><a class="tablelink" id="table_' . $res[$idx] . '" href="' . str_replace('/index.html', '/', $URIs[0]) . $res[$idx] . '.html">' . $res[$idx] . '</a></li>' . PHP_EOL;
                 }
                 $basehtml .= '</ul>' . PHP_EOL;
             } else {
                 $requestParams = $this->getRequestParams();
                 $basehtml .= '<h2>' . $this->restResourceModel . '</h2>' . PHP_EOL;
                 if (TRUE === $this->restResourceListed) {
                     $basehtml .= '<h3><form id="crud-form-search" class="crud-form" method="GET"><input type="text" value="' . (isset($requestParams['LIKE']) ? $requestParams['LIKE'] : '') . '" name="LIKE"/><div class="submit-button search-button"><input type="submit" value="search"/></div></form></h3>' . PHP_EOL;
                     if (isset($res[0])) {
                         $basehtml .= '<table class="list">' . PHP_EOL;
                         // リストヘッダ
                         $basehtml .= '<tr>' . PHP_EOL;
                         foreach ($res[0] as $key => $val) {
                             $order = $requestParams['ORDER'];
                             if (strlen($order) > 0 && 0 === strpos($order, $key) && FALSE !== strpos($order, 'DESC')) {
                                 $order = rawurlencode($key . ' ASC');
                             } else {
                                 $order = rawurlencode($key . ' DESC');
                             }
                             $basehtml .= '<th class="crudkey"><a class="crudlink" id="crud_order_' . $this->restResourceModel . '_' . $key . '" href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=0&total=' . $requestParams['total'] . '&ORDER=' . $order . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">' . $key . '</a></th>';
                         }
                         $basehtml .= '</tr>' . PHP_EOL;
                         for ($idx = 0; $idx < count($res); $idx++) {
                             $basehtml .= '<tr>' . PHP_EOL;
                             $id = '';
                             foreach ($res[$idx] as $key => $val) {
                                 if ('' === $id) {
                                     $id = $val;
                                 }
                                 $basehtml .= '<td><a class="crudlink" id="crud_' . $this->restResourceModel . '_' . $id . '" target="_blank" href="' . str_replace('/' . $this->restResourceModel . '.html', '/' . $this->restResourceModel . '/' . $id . '.html', $URIs[0]) . '">' . $val . '</a></td>';
                             }
                             $basehtml .= '</tr>' . PHP_EOL;
                         }
                         $basehtml .= '</table>' . PHP_EOL;
                         if (isset($requestParams['LIMIT']) && is_numeric($requestParams['LIMIT']) && (int) $requestParams['LIMIT'] > 0 && isset($requestParams['OFFSET']) && is_numeric($requestParams['OFFSET']) && isset($requestParams['total']) && is_numeric($requestParams['total']) && (int) $requestParams['total'] > 0) {
                             // ページング
                             $nowPage = floor((int) $requestParams['OFFSET'] / (int) $requestParams['LIMIT']) + 1;
                             if (1 < floor((int) $requestParams['total'] / (int) $requestParams['LIMIT']) + 1) {
                                 $basehtml .= '<table class="paging"><tr>' . PHP_EOL;
                                 if ($nowPage > 1) {
                                     // 先頭リンク
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=0&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">&lt;&lt;</a></td>' . PHP_EOL;
                                     // 前へリンク
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . ((int) $requestParams['OFFSET'] - (int) $requestParams['LIMIT']) . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">&lt;</a></td>' . PHP_EOL;
                                 }
                                 // 2つ前のページ
                                 if ($nowPage - 2 > 0) {
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . ((int) $requestParams['OFFSET'] - (int) $requestParams['LIMIT'] * 2) . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">' . ($nowPage - 2) . '</a></td>' . PHP_EOL;
                                 }
                                 // 1つ前のページ
                                 if ($nowPage - 1 > 0) {
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . ((int) $requestParams['OFFSET'] - (int) $requestParams['LIMIT']) . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">' . ($nowPage - 1) . '</a></td>' . PHP_EOL;
                                 }
                                 // 現在ページ
                                 $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . $requestParams['OFFSET'] . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">' . $nowPage . '</a></td>' . PHP_EOL;
                                 // 1つ次のページ
                                 if ($nowPage + 1 <= floor((int) $requestParams['total'] / (int) $requestParams['LIMIT'])) {
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . ((int) $requestParams['OFFSET'] + (int) $requestParams['LIMIT']) . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">' . ($nowPage + 1) . '</a></td>' . PHP_EOL;
                                 }
                                 // 2つ次のページ
                                 if ($nowPage + 2 <= floor((int) $requestParams['total'] / (int) $requestParams['LIMIT'])) {
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . ((int) $requestParams['OFFSET'] + (int) $requestParams['LIMIT'] * 2) . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">' . ($nowPage + 2) . '</a></td>' . PHP_EOL;
                                 }
                                 if ($nowPage < floor((int) $requestParams['total'] / (int) $requestParams['LIMIT'])) {
                                     // 次へリンク
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . ((int) $requestParams['OFFSET'] + (int) $requestParams['LIMIT']) . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">&gt;</a></td>' . PHP_EOL;
                                     // 終端リンク
                                     $basehtml .= '<td class="list-paginglink"><a href="' . $URIs[0] . '?LIMIT=' . $requestParams['LIMIT'] . '&OFFSET=' . (floor((int) $requestParams['total'] / (int) $requestParams['LIMIT']) - 1) * (int) $requestParams['LIMIT'] . '&total=' . $requestParams['total'] . '&ORDER=' . rawurlencode($requestParams['ORDER']) . '&LIKE=' . rawurlencode($requestParams['LIKE']) . '">&gt;&gt;</a></td>' . PHP_EOL;
                                 }
                                 $basehtml .= '</tr></table>' . PHP_EOL;
                             }
                         }
                         $basehtml .= '<div class="csv-download-link"><a href="' . str_replace('.html', '.csv', $_SERVER['REQUEST_URI']) . '">download csv</a></div>' . PHP_EOL;
                         $basehtml .= '<div class="csv-all-download-link"><a href="' . str_replace('.html', '.csv', $URIs[0]) . '?ORDER=' . rawurlencode($requestParams['ORDER']) . '">download csv all records</a></div>' . PHP_EOL;
                         $basehtml .= '<div class="tablelist-link"><a href="' . str_replace('/' . $this->restResourceModel . '.html', '/index.html', $URIs[0]) . '">table list</a></div>' . PHP_EOL;
                     }
                 } else {
                     if (isset($res[0])) {
                         $basehtml .= '<form id="crud-form-put" class="crud-form" method="POST">' . PHP_EOL;
                         $basehtml .= '<table class="detail">' . PHP_EOL;
                         $id = '';
                         foreach ($res[0] as $key => $val) {
                             if ('' === $id) {
                                 $id = $val;
                             }
                             $basehtml .= '<tr><th class="crudkey">' . $key . '</th></tr>' . PHP_EOL;
                             $basehtml .= '<tr><td><input type="text" name="' . $key . '" value="' . htmlspecialchars($val) . '"/></td></tr>' . PHP_EOL;
                         }
                         $basehtml .= '<tr><td><div class="submit-button put-button"><input type="submit"/ value="PUT"></div></td></tr>' . PHP_EOL;
                         $basehtml .= '<input type="hidden" name="_method_" value="PUT"/>' . PHP_EOL;
                         $basehtml .= '</table>' . PHP_EOL;
                         $basehtml .= '</form>' . PHP_EOL;
                         $basehtml .= '<form id="crud-form-delete" class="crud-form" method="POST">' . PHP_EOL;
                         $basehtml .= '<div class="submit-button delete-button"><input type="submit"/ value="DELETE"></div>' . PHP_EOL;
                         $basehtml .= '<input type="hidden" name="_method_" value="DELETE"/>' . PHP_EOL;
                         $basehtml .= '</form>' . PHP_EOL;
                         $basehtml .= '<div class="list-link"><a href="' . str_replace('/' . $this->restResourceModel . '/' . $id . '.html', '/' . $this->restResourceModel . '.html', $URIs[0]) . '">' . $this->restResourceModel . ' list</a></div>' . PHP_EOL;
                     } else {
                         $basehtml .= '<div class="list-link"><a href="javascript:history.back()">back</a></div>' . PHP_EOL;
                     }
                 }
             }
             $res = $basehtml;
         }
     }
     if ('HEAD' === $this->requestMethod && isset($res['describes'])) {
         header('Head: ' . json_encode($res['describes']));
         header('Rules: ' . json_encode($res['rules']));
         header('Records: ' . $res['count']);
         $res = TRUE;
     }
     // 正常終了(のハズ!)
     return $res;
 }
Пример #2
0
 /**
  * 次のFlowを特定し、ロードし、そのクラス名を返却する
  * @param string クラス名
  * @param string ターゲットファイルパスのヒント
  * @return mixed 成功時は対象のクラス名 失敗した場合はFALSEを返す
  */
 public static function loadNextFlow($argClassName = NULL, $argTargetPath = '')
 {
     // 先ずbackflowなのかどうか
     if ('backflow' === strtolower($argClassName)) {
         // backflowが特定出来無かった時ように強制的にIndexを指定しておく
         $argClassName = 'index';
         if (strlen($argTargetPath) > 0) {
             $argClassName = $argTargetPath . '/' . $argClassName;
         }
         // PostパラメータからBackflowを特定する
         if (isset($_POST['flowpostformsection-backflow-section'])) {
             $argClassName = $_POST['flowpostformsection-backflow-section'];
             // 				if(FALSE !== strpos($argClassName, '/')){
             // 					// sectionとtargetを分割する
             // 					$targetTmp = explode('/', $argClassName);
             // 					// 最後だけをsectionIDとして使う
             // 					$argClassName = $targetTmp[count($targetTmp)-1];
             // 					unset($targetTmp[count($targetTmp)-1]);
             // 					$argTargetPath = implode('/', $targetTmp) . '/';
             // 				}
             // 				if(FALSE !== strpos($argClassName, '-')){
             // 					$argClassName = str_replace('-', '_', $argClassName);
             // 				}
         }
         // backflowはリダイレクトポスト(307リダイレクト)
         $query = '';
         if (isset($_POST['flowpostformsection-backflow-section-query']) && strlen($_POST['flowpostformsection-backflow-section-query']) > 0) {
             $query = $_POST['flowpostformsection-backflow-section-query'];
         }
         header('Location: ./' . self::reverseRewriteURL('?_c_=' . $argClassName . '&_o_=' . $_GET['_o_'], $query), TRUE, 307);
         exit;
     }
     $className = MVCCore::loadMVCModule($argClassName, FALSE, $argTargetPath);
     debug('backflowClass=' . var_export($className, true));
     return $className;
 }