PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/plugins/DBML/register/object.php

https://github.com/tomk79/PxPlugin_DBML
PHP | 391 lines | 271 code | 60 blank | 60 comment | 37 complexity | 7ac45ad4d6feb16fef8a14a4a8158cea MD5 | raw file
  1. <?php
  2. /**
  3. * PX Plugin "DBML"
  4. * @author Tomoya Koyanagi.
  5. */
  6. class pxplugin_DBML_register_object{
  7. private $px;
  8. private $path_dbml;
  9. private $database_define;
  10. /**
  11. * コンストラクタ
  12. */
  13. public function __construct($px){
  14. $this->px = $px;
  15. $this->path_dbml = $px->get_conf('plugin-DBML.path_dbml');
  16. $this->parse_dbml();
  17. }//__construct()
  18. /**
  19. * factory: XML DOM Parser
  20. */
  21. private function factory_dom_parser( $src ){
  22. $class_name = $this->px->load_px_plugin_class( '/DBML/libs/PxXMLDomParser/PxXMLDomParser.php' );
  23. $dom_parser = new $class_name( $src, 'bin' );
  24. return $dom_parser;
  25. }//factory_dom_parser()
  26. /**
  27. * DBMLファイルをパースして、内容を整理する。
  28. */
  29. private function parse_dbml(){
  30. $this->database_define = array();
  31. $this->database_define['tables'] = array();
  32. $src = $this->px->dbh()->file_get_contents( $this->path_dbml );
  33. $dom_parser = $this->factory_dom_parser($src);
  34. $tables = $dom_parser->find('dbml > tables > table');
  35. foreach($tables as $table){
  36. $table_info = array();
  37. $table_info['name'] = $table['attributes']['name'] ;
  38. $table_info['logical_name'] = $table['attributes']['logical-name'];
  39. $table_info['skip_create'] = $table['attributes']['skip-create'] ;
  40. $table_info['columns'] = array();
  41. // 値のチューニング
  42. $table_info['name'] = $this->bind_meta_string($table_info['name']);
  43. $table_info['skip_create'] = $this->judge_boolean($table_info['skip_create']);
  44. // / 値のチューニング
  45. $dom_parser = $this->factory_dom_parser($table['innerHTML']);
  46. $columns = $dom_parser->find('column');
  47. foreach($columns as $column){
  48. $column_info = array();
  49. $column_info['name'] = $column['attributes']['name'] ;
  50. $column_info['logical_name'] = $column['attributes']['logical-name'];
  51. $column_info['type'] = $column['attributes']['type'] ;
  52. $column_info['size'] = $column['attributes']['size'] ;
  53. $column_info['not_null'] = $column['attributes']['not-null'] ;
  54. $column_info['default'] = $column['attributes']['default'] ;
  55. $column_info['key_type'] = $column['attributes']['key-type'] ;
  56. $column_info['foreign_key'] = $column['attributes']['foreign-key'] ;
  57. $column_info['unique'] = $column['attributes']['unique'] ;
  58. // 値のチューニング
  59. $column_info['name'] = $this->bind_meta_string($column_info['name']);
  60. $column_info['size'] = (strlen($column_info['size'])?intval($column_info['size']):null);
  61. $column_info['unique'] = $this->judge_boolean($column_info['unique']);
  62. $column_info['not_null'] = $this->judge_boolean($column_info['not_null']);
  63. $column_info['foreign_key'] = $this->bind_meta_string($column_info['foreign_key']);
  64. // / 値のチューニング
  65. array_push( $table_info['columns'], $column_info );
  66. }
  67. array_push( $this->database_define['tables'], $table_info );
  68. }
  69. return true;
  70. }//parse_dbml()
  71. /**
  72. * 埋め込み情報をバインドする
  73. */
  74. private function bind_meta_string( $text ){
  75. if(!is_string($text)){return $text;}
  76. $text = preg_replace( '/\{\$prefix\}/' , $this->px->get_conf('dbms.prefix') , $text );
  77. return $text;
  78. }//bind_meta_string()
  79. /**
  80. * ブール型となる予定の入力値を評価し、結論を返す
  81. */
  82. private function judge_boolean( $text ){
  83. switch(strtolower($text)){
  84. case 'true':
  85. $text = true; break;
  86. default:
  87. $text = false; break;
  88. }
  89. return $text;
  90. }//judge_boolean()
  91. /**
  92. * データベース定義配列を取り出す。
  93. */
  94. public function get_db_definition(){
  95. return $this->database_define;
  96. }//get_db_definition()
  97. /**
  98. * テーブル定義配列を取り出す。
  99. */
  100. public function get_table_definition( $table_name ){
  101. $table_name = $this->bind_meta_string($table_name);
  102. foreach( $this->database_define['tables'] as $table_info ){
  103. if($table_info['name'] == $table_name){
  104. return $table_info;
  105. }
  106. }
  107. return false;
  108. }//get_table_definition()
  109. /**
  110. * テーブルのレコード数を数える
  111. */
  112. public function get_count_table_rows( $table_name ){
  113. $table_name = $this->bind_meta_string($table_name);
  114. ob_start();?>
  115. SELECT count(*) AS count FROM :D:table_name;
  116. <?php
  117. $sql = @ob_get_clean();
  118. $bind_data = array(
  119. 'table_name'=>$table_name,
  120. );
  121. $sql = $this->px->dbh()->bind( $sql , $bind_data );
  122. $res = $this->px->dbh()->send_query( $sql );
  123. if( !$res ){
  124. return false;
  125. }
  126. $value = $this->px->dbh()->get_results();
  127. return intval($value[0]['count']);
  128. }//get_count_table_rows()
  129. /**
  130. * テーブルに行を追加する
  131. */
  132. public function insert( $table_name, $row ){
  133. $table_name = $this->bind_meta_string($table_name);
  134. $table_definition = $this->get_table_definition($table_name);
  135. $ary_key = array();
  136. $ary_val = array();
  137. $bind_data = array();
  138. foreach( $table_definition['columns'] as $column_info ){
  139. // シリアル型(=auto inclement)は、指定できない。
  140. if($column_info['type'] == 'series'){
  141. continue;
  142. }
  143. // VARCHARマスターキーを自動生成
  144. if( $column_info['key_type'] == 'primary' && $column_info['type'] == 'varchar' && is_null( $row[$column_info['name']] ) ){
  145. $row[$column_info['name']] = uniqid();
  146. }
  147. // メタ文字の接頭辞を決める
  148. $type_prefix = ':S:';
  149. switch($column_info['type']){
  150. case 'int':
  151. case 'serial':
  152. $type_prefix = ':N:';
  153. break;
  154. default:
  155. $type_prefix = ':S:';
  156. }
  157. // NOT NULL の処理
  158. if( $column_info['not_null'] && is_null($row[$column_info['name']])){
  159. if( !is_null($column_info['default']) ){
  160. $row[$column_info['name']] = $column_info['default'];
  161. }else{
  162. // NOT NULL でかつ DEFAULT が指定されていないカラムに
  163. // NULL を入れようとした場合は、続行不能。
  164. return false;
  165. }
  166. }
  167. // DATETIME型の "NOW" を処理。
  168. if( $column_info['type'] == 'datetime' && strtolower($row[$column_info['name']]) == 'now' ){
  169. $row[$column_info['name']] = date('Y-m-d H:i:s');
  170. }
  171. // 要素をセット
  172. $bind_data[$column_info['name']] = $row[$column_info['name']];
  173. array_push($ary_key,$column_info['name']);
  174. array_push($ary_val,$type_prefix.$column_info['name']);
  175. }
  176. $sql = '';
  177. $sql .= 'INSERT ';
  178. $sql .= 'INTO '.$this->px->dbh()->bind( ':D:table_name' , array('table_name'=>$table_name) ).' ';
  179. $sql .= '('.implode(',',$ary_key).') ';
  180. $sql .= 'VALUES ('.implode(',',$ary_val).')';
  181. $sql .= ';';
  182. $sql = $this->px->dbh()->bind( $sql , $bind_data );
  183. $res = $this->px->dbh()->send_query( $sql );
  184. if( !$res ){
  185. return false;
  186. }
  187. return true;
  188. }//insert()
  189. /**
  190. * テーブルの行を書き換える
  191. */
  192. public function update( $table_name, $conditions, $row ){
  193. $table_name = $this->bind_meta_string($table_name);
  194. $table_definition = $this->get_table_definition($table_name);
  195. $ary_conditions = array();
  196. $ary_key_val = array();
  197. $bind_data = array();
  198. foreach( $table_definition['columns'] as $column_info ){
  199. // メタ文字の接頭辞を決める
  200. $type_prefix = ':S:';
  201. switch($column_info['type']){
  202. case 'int':
  203. case 'serial':
  204. $type_prefix = ':N:';
  205. break;
  206. default:
  207. $type_prefix = ':S:';
  208. }
  209. // DATETIME型の "NOW" を処理。
  210. if( $column_info['type'] == 'datetime' ){
  211. if( strtolower($row[$column_info['name']]) == 'now' ){ $row[$column_info['name']] = date('Y-m-d H:i:s'); }
  212. if( strtolower($conditions[$column_info['name']]) == 'now' ){ $conditions[$column_info['name']] = date('Y-m-d H:i:s'); }
  213. }
  214. // 要素をセット
  215. if( array_key_exists( $column_info['name'], $row ) ){
  216. $bind_data['VALUES_'.$column_info['name']] = $row[$column_info['name']];
  217. array_push($ary_key_val, $column_info['name'].'='.$type_prefix.'VALUES_'.$column_info['name']);
  218. }
  219. if( array_key_exists( $column_info['name'], $conditions ) ){
  220. array_push($ary_conditions, $column_info['name'].'='.$type_prefix.'CONDITIONS_'.$column_info['name']);
  221. }
  222. }
  223. // 条件式のバインドデータを作成
  224. foreach( $conditions as $key=>$val ){
  225. $bind_data['CONDITIONS_'.$key] = $val;
  226. }
  227. $sql = '';
  228. $sql .= 'UPDATE ';
  229. $sql .= ''.$this->px->dbh()->bind( ':D:table_name' , array('table_name'=>$table_name) ).' ';
  230. if(count($ary_key_val)){
  231. $sql .= 'SET ';
  232. $sql .= ''.implode(', ',$ary_key_val).' ';
  233. }
  234. if(count($ary_conditions)){
  235. $sql .= 'WHERE ';
  236. $sql .= ''.implode(' AND ',$ary_conditions).' ';
  237. }
  238. $sql .= ';';
  239. $sql = $this->px->dbh()->bind( $sql , $bind_data );
  240. $res = $this->px->dbh()->send_query( $sql );
  241. if( !$res ){
  242. return false;
  243. }
  244. return true;
  245. }//update()
  246. /**
  247. * テーブルから行を取得する
  248. */
  249. public function select( $table_name, $conditions, $limit = null, $offset = 0 ){
  250. $table_name = $this->bind_meta_string($table_name);
  251. $offset = intval( $offset );
  252. if( !is_null( $limit ) ){
  253. $limit = intval( $limit );
  254. }
  255. $table_definition = $this->get_table_definition($table_name);
  256. $ary_conditions = array();
  257. $bind_data = array();
  258. foreach( $table_definition['columns'] as $column_info ){
  259. if( !array_key_exists( $column_info['name'], $conditions ) ){ continue; }
  260. // メタ文字の接頭辞を決める
  261. $type_prefix = ':S:';
  262. switch($column_info['type']){
  263. case 'int':
  264. case 'serial':
  265. $type_prefix = ':N:';
  266. break;
  267. default:
  268. $type_prefix = ':S:';
  269. }
  270. // 要素をセット
  271. $bind_data['CONDITIONS_'.$column_info['name']] = $conditions[$column_info['name']];
  272. array_push($ary_conditions,$column_info['name'].'='.$type_prefix.'CONDITIONS_'.$column_info['name']);
  273. }
  274. $sql = '';
  275. $sql .= 'SELECT * ';
  276. $sql .= 'FROM '.$this->px->dbh()->bind( ':D:table_name' , array('table_name'=>$table_name) ).' ';
  277. if(count($ary_conditions)){
  278. $sql .= 'WHERE ';
  279. $sql .= ''.implode(' AND ',$ary_conditions).' ';
  280. }
  281. if( $limit > 0 ){
  282. $sql .= $this->px->dbh()->mk_sql_limit($limit, $offset);
  283. }
  284. $sql .= ';';
  285. $sql = $this->px->dbh()->bind( $sql , $bind_data );
  286. $res = $this->px->dbh()->send_query( $sql );
  287. if( !$res ){
  288. return false;
  289. }
  290. $value = $this->px->dbh()->get_results();
  291. return $value;
  292. }//select()
  293. /**
  294. * テーブルの行を削除する
  295. */
  296. public function delete( $table_name, $conditions ){
  297. $table_name = $this->bind_meta_string($table_name);
  298. $table_definition = $this->get_table_definition($table_name);
  299. $ary_conditions = array();
  300. $bind_data = array();
  301. foreach( $table_definition['columns'] as $column_info ){
  302. if( !array_key_exists( $column_info['name'], $conditions ) ){ continue; }
  303. // メタ文字の接頭辞を決める
  304. $type_prefix = ':S:';
  305. switch($column_info['type']){
  306. case 'int':
  307. case 'serial':
  308. $type_prefix = ':N:';
  309. break;
  310. default:
  311. $type_prefix = ':S:';
  312. }
  313. // 要素をセット
  314. $bind_data['CONDITIONS_'.$column_info['name']] = $conditions[$column_info['name']];
  315. array_push($ary_conditions,$column_info['name'].'='.$type_prefix.'CONDITIONS_'.$column_info['name']);
  316. }
  317. $sql = '';
  318. $sql .= 'DELETE ';
  319. $sql .= 'FROM '.$this->px->dbh()->bind( ':D:table_name' , array('table_name'=>$table_name) ).' ';
  320. $sql .= 'WHERE ';
  321. $sql .= ''.implode(' AND ',$ary_conditions).' ';
  322. $sql .= ';';
  323. $sql = $this->px->dbh()->bind( $sql , $bind_data );
  324. $res = $this->px->dbh()->send_query( $sql );
  325. if( !$res ){
  326. return false;
  327. }
  328. return true;
  329. }//delete()
  330. }
  331. ?>