OSDN Git Service

- Ethna_DBクラスを抽象クラス(扱い)として新たにEthna_DBクラスを実装したEthna_DB_PEARクラスを追加
[ethna/ethna.git] / class / Ethna_AppObject.php
1 <?php
2 // vim: foldmethod=marker
3 /**
4  *      Ethna_AppObject.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$
10  */
11
12 // {{{ Ethna_AppObject
13 /**
14  *      ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ù¡¼¥¹¥¯¥é¥¹
15  *
16  *      @author         Masaki Fujimoto <fujimoto@php.net>
17  *      @access         public
18  *      @package        Ethna
19  *      @todo           Ê£¿ô¥Æ¡¼¥Ö¥ë¤ÎJOINÂбþ
20  */
21 class Ethna_AppObject
22 {
23         /**#@+
24          *      @access private
25          */
26
27         /**     @var    object  Ethna_Backend           backend¥ª¥Ö¥¸¥§¥¯¥È */
28         var $backend;
29
30         /**     @var    object  Ethna_Config            ÀßÄꥪ¥Ö¥¸¥§¥¯¥È */
31         var $config;
32
33         /**  @var    object  Ethna_DB      DB¥ª¥Ö¥¸¥§¥¯¥È */
34         var $db;
35
36         /**     @var    object  Ethna_I18N                      i18n¥ª¥Ö¥¸¥§¥¯¥È */
37         var $i18n;
38
39         /**     @var    object  Ethna_ActionForm        ¥¢¥¯¥·¥ç¥ó¥Õ¥©¡¼¥à¥ª¥Ö¥¸¥§¥¯¥È */
40         var $action_form;
41
42         /**     @var    object  Ethna_ActionForm        ¥¢¥¯¥·¥ç¥ó¥Õ¥©¡¼¥à¥ª¥Ö¥¸¥§¥¯¥È(¾Êά·Á) */
43         var $af;
44
45         /**     @var    object  Ethna_Session           ¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È */
46         var $session;
47
48         /**     @var    array   ¥Æ¡¼¥Ö¥ëÄêµÁ */
49         var     $table_def = array();
50
51         /**     @var    array   ¥×¥í¥Ñ¥Æ¥£ÄêµÁ */
52         var     $prop_def = array();
53
54         /**     @var    array   ¥×¥í¥Ñ¥Æ¥£ */
55         var     $prop = null;
56         var $prop_backup = null;
57
58         /** @var        array   ¥×¥é¥¤¥Þ¥ê¥­¡¼ÄêµÁ */
59         var     $id_def = null;
60
61         /**     @var    int             ¥ª¥Ö¥¸¥§¥¯¥ÈID */
62         var     $id = null;
63
64         /**#@-*/
65
66
67         /**
68          *      Ethna_AppObject¥¯¥é¥¹¤Î¥³¥ó¥¹¥È¥é¥¯¥¿
69          *
70          *      @access public
71          *      @param  object  Ethna_Backend   &$backend       Ethna_Backend¥ª¥Ö¥¸¥§¥¯¥È
72          *      @param  mixed   $key_type       ¸¡º÷¥­¡¼Ì¾
73          *      @param  mixed   $key            ¸¡º÷¥­¡¼
74          *      @param  array   $prop           ¥×¥í¥Ñ¥Æ¥£°ìÍ÷
75          *      @return mixed   0:Àµ¾ï½ªÎ» -1:¥­¡¼/¥×¥í¥Ñ¥Æ¥£Ì¤»ØÄê Ethna_Error:¥¨¥é¡¼
76          */
77         function Ethna_AppObject(&$backend, $key_type = null, $key = null, $prop = null)
78         {
79                 $this->backend =& $backend;
80                 $this->config =& $backend->getConfig();
81                 $this->action_form =& $backend->getActionForm();
82                 $this->af =& $this->action_form;
83                 $this->session =& $backend->getSession();
84
85                 $db_list = $backend->getDBList();
86                 if (Ethna::isError($db_list) == false) {
87                         foreach ($db_list as $elt) {
88                                 $varname = $elt['varname'];
89                                 $this->$varname =& $elt['db'];
90
91                                 if ($elt['type'] == DB_TYPE_RW) {
92                                         $this->my_db_rw =& $elt['db'];
93                                 } else if ($elt['type'] == DB_TYPE_RO) {
94                                         $this->my_db_ro =& $elt['db'];
95                                 }
96                         }
97                 }
98                 if (isset($this->my_db_ro) == false && $this->my_db_rw) {
99                         $this->my_db_ro =& $this->my_db_rw;
100                 }
101
102                 $c =& $backend->getController();
103
104                 // Ethna_AppManager¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀßÄê
105                 $manager_list = $c->getManagerList();
106                 foreach ($manager_list as $k => $v) {
107                         $this->$k = $backend->getManager($v);
108                 }
109
110                 // ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥×¥é¥¤¥Þ¥ê¥­¡¼ÄêµÁ¹½ÃÛ
111                 foreach ($this->prop_def as $k => $v) {
112                         if ($v['primary'] == false) {
113                                 continue;
114                         }
115                         if (is_null($this->id_def)) {
116                                 $this->id_def = $k;
117                         } else if (is_array($this->id_def)) {
118                                 $this->id_def[] = $k;
119                         } else {
120                                 $this->id_def = array($this->id_def, $k);
121                         }
122                 }
123                 
124                 // DB¥¨¥é¡¼¥Á¥§¥Ã¥¯
125                 if (is_null($this->my_db_ro)) {
126                         return Ethna::raiseError("Ethna_AppObject¤òÍøÍѤ¹¤ë¤Ë¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹ÀßÄ꤬ɬÍפǤ¹", E_DB_NODSN);
127                 } else if (Ethna::isError($db_list)) {
128                         return $db_list;
129                 }
130
131                 // ¥­¡¼ÂÅÅöÀ­¥Á¥§¥Ã¥¯
132                 if (is_null($key_type) && is_null($key) && is_null($prop)) {
133                         // perhaps for adding object
134                         return 0;
135                 }
136
137                 // ¥×¥í¥Ñ¥Æ¥£ÀßÄê
138                 if (is_null($prop)) {
139                         $this->_setPropByDB($key_type, $key);
140                 } else {
141                         $this->_setPropByValue($prop);
142                 }
143
144                 $this->prop_backup = $this->prop;
145
146                 if (is_array($this->id_def)) {
147                         $this->id = array();
148                         foreach ($this->id_def as $k) {
149                                 $this->id[] = $this->prop[$k];
150                         }
151                 } else {
152                         $this->id = $this->prop[$this->id_def];
153                 }
154
155                 return 0;
156         }
157
158         /**
159          *      Í­¸ú¤Ê¥ª¥Ö¥¸¥§¥¯¥È¤«¤É¤¦¤«¤òÊÖ¤¹
160          *
161          *      @access public
162          *      @return bool    true:Í­¸ú false:̵¸ú
163          */
164         function isValid()
165         {
166                 return is_null($this->id) ? false : true;
167         }
168
169         /**
170          *      ¥¢¥¯¥Æ¥£¥Ö¤Ê¥ª¥Ö¥¸¥§¥¯¥È¤«¤É¤¦¤«¤òÊÖ¤¹
171          *
172          *      isValid()¥á¥½¥Ã¥É¤Ï¥ª¥Ö¥¸¥§¥¯¥È¼«ÂΤ¬Í­¸ú¤«¤É¤¦¤«¤òȽÄꤹ¤ë¤Î¤ËÂФ·
173          *      isActive()¤Ï¥ª¥Ö¥¸¥§¥¯¥È¤¬¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤È¤·¤ÆÍ­¸ú¤«¤É¤¦¤«¤òÊÖ¤¹
174          *
175          *      @access public
176          *      @return bool    true:¥¢¥¯¥Æ¥£¥Ö false:Èó¥¢¥¯¥Æ¥£¥Ö
177          */
178         function isActive()
179         {
180                 if ($this->isValid() == false) {
181                         return false;
182                 }
183                 return $this->prop['state'] == OBJECT_STATE_ACTIVE ? true : false;
184         }
185
186         /**
187          *      ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥×¥í¥Ñ¥Æ¥£ÄêµÁ¤òÊÖ¤¹
188          *
189          *      @access public
190          *      @return array   ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥×¥í¥Ñ¥Æ¥£ÄêµÁ
191          */
192         function getDef()
193         {
194                 return $this->prop_def;
195         }
196
197         /**
198          *      ¥×¥é¥¤¥Þ¥ê¥­¡¼ÄêµÁ¤òÊÖ¤¹
199          *
200          *      @access public
201          *      @return mixed   ¥×¥é¥¤¥Þ¥ê¥­¡¼¤È¤Ê¤ë¥×¥í¥Ñ¥Æ¥£Ì¾
202          */
203         function getIdDef()
204         {
205                 return $this->id_def;
206         }
207
208         /**
209          *      ¥ª¥Ö¥¸¥§¥¯¥ÈID¤òÊÖ¤¹
210          *
211          *      @access public
212          *      @return mixed   ¥ª¥Ö¥¸¥§¥¯¥ÈID
213          */
214         function getId()
215         {
216                 return $this->id;
217         }
218
219         /**
220          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤Ø¤Î¥¢¥¯¥»¥µ(R)
221          *
222          *      @access public
223          *      @param  string  $key    ¥×¥í¥Ñ¥Æ¥£Ì¾
224          *      @return mixed   ¥×¥í¥Ñ¥Æ¥£
225          */
226         function get($key)
227         {
228                 if (isset($this->prop_def[$key]) == false) {
229                         trigger_error(sprintf("Unknown property [%s]", $key), E_USER_ERROR);
230                         return null;
231                 }
232                 if (isset($this->prop[$key])) {
233                         return $this->prop[$key];
234                 }
235                 return null;
236         }
237
238         /**
239          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£É½¼¨Ì¾¤Ø¤Î¥¢¥¯¥»¥µ
240          *
241          *      @access public
242          *      @param  string  $key    ¥×¥í¥Ñ¥Æ¥£Ì¾
243          *      @return string  ¥×¥í¥Ñ¥Æ¥£¤Îɽ¼¨Ì¾
244          */
245         function getName($key)
246         {
247                 return $this->get($key);
248         }
249
250         /**
251          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£É½¼¨Ì¾(¾ÜºÙ)¤Ø¤Î¥¢¥¯¥»¥µ
252          *
253          *      @access public
254          *      @param  string  $key    ¥×¥í¥Ñ¥Æ¥£Ì¾
255          *      @return string  ¥×¥í¥Ñ¥Æ¥£¤Îɽ¼¨Ì¾(¾ÜºÙ)
256          */
257         function getLongName($key)
258         {
259                 return $this->get($key);
260         }
261
262         /**
263          *      ¥×¥í¥Ñ¥Æ¥£É½¼¨Ì¾¤ò³ÊǼ¤·¤¿Ï¢ÁÛÇÛÎó¤ò¼èÆÀ¤¹¤ë
264          *
265          *      @access public
266          *      @return array   ¥×¥í¥Ñ¥Æ¥£É½¼¨Ì¾¤ò³ÊǼ¤·¤¿Ï¢ÁÛÇÛÎó
267          */
268         function getNameObject()
269         {
270                 $object = array();
271
272                 foreach ($this->prop_def as $key => $elt) {
273                         $object[$elt['form_name']] = $this->getName($key);
274                 }
275
276                 return $object;
277         }
278
279         /**
280          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤Ø¤Î¥¢¥¯¥»¥µ(W)
281          *
282          *      @access public
283          *      @param  string  $key    ¥×¥í¥Ñ¥Æ¥£Ì¾
284          *      @param  string  $value  ¥×¥í¥Ñ¥Æ¥£ÃÍ
285          */
286         function set($key, $value)
287         {
288                 if (isset($this->prop_def[$key]) == false) {
289                         trigger_error(sprintf("Unknown property [%s]", $key), E_USER_ERROR);
290                         return null;
291                 }
292                 $this->prop[$key] = $value;
293         }
294
295         /**
296          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò»ØÄê¤Î·Á¼°¤Ç¥À¥ó¥×¤¹¤ë(¸½ºß¤ÏCSV·Á¼°¤Î¤ß¥µ¥Ý¡¼¥È)
297          *
298          *      @access public
299          *      @param  string  $type   ¥À¥ó¥×·Á¼°("csv"...)
300          *      @return string  ¥À¥ó¥×·ë²Ì(¥¨¥é¡¼¤Î¾ì¹ç¤Ïnull)
301          */
302         function dump($type = "csv")
303         {
304                 $method = "_dump_$type";
305                 if (method_exists($this, $method) == false) {
306                         return Ethna::raiseError("¥á¥½¥Ã¥É̤ÄêµÁ[%s]", E_APP_NOMETHOD, $method);
307                 }
308
309                 return $this->$method();
310         }
311
312         /**
313          *      ¥Õ¥©¡¼¥àÃͤ«¤é¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò¥¤¥ó¥Ý¡¼¥È¤¹¤ë
314          *
315          *      @access public
316          *      @param  int             $option ¥¤¥ó¥Ý¡¼¥È¥ª¥×¥·¥ç¥ó(OBJECT_IMPORT_IGNORE_NULL,...)
317          */
318         function importForm($option = null)
319         {
320                 foreach ($this->getDef() as $k => $def) {
321                         $value = $this->af->get($def['form_name']);
322                         if (is_null($value)) {
323                                 // ¥Õ¥©¡¼¥à¤«¤éÃͤ¬Á÷¿®¤µ¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤Î¿¶Éñ¤¤
324                                 if ($option == OBJECT_IMPORT_IGNORE_NULL) {
325                                         // null¤Ï¥¹¥­¥Ã¥×
326                                         continue;
327                                 } else if ($option == OBJECT_IMPORT_CONVERT_NULL) {
328                                         // ¶õʸ»úÎó¤ËÊÑ´¹
329                                         $value = '';
330                                 }
331                         }
332                         $this->set($k, $value);
333                 }
334         }
335
336         /**
337          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Õ¥©¡¼¥àÃͤ˥¨¥¯¥¹¥Ý¡¼¥È¤¹¤ë
338          *
339          *      @access public
340          */
341         function exportForm()
342         {
343                 foreach ($this->getDef() as $k => $def) {
344                         $this->af->set($def['form_name'], $this->get($k));
345                 }
346         }
347
348         /**
349          *      ¥ª¥Ö¥¸¥§¥¯¥È¤òÄɲ乤ë
350          *
351          *      @access public
352          *      @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
353          *      @todo   MySQL°Ê³°¤Î¥·¡¼¥±¥ó¥¹·¿(Ū¤Ê¤â¤Î)Âбþ
354          */
355         function add()
356         {
357                 $sql = $this->_getSQL_Add();
358                 for ($i = 0; $i < 4; $i++) {
359                         $r =& $this->my_db_rw->query($sql);
360                         if (Ethna::isError($r)) {
361                                 if ($r->getCode() == E_DB_DUPENT) {
362                                         // ½ÅÊ£¥¨¥é¡¼¥­¡¼¤ÎȽÊÌ
363                                         $duplicate_key_list = $this->_getDuplicateKeyList();
364                                         if (Ethna::isError($duplicate_key_list)) {
365                                                 return $duplicate_key_list;
366                                         }
367                                         if (is_array($duplicate_key_list) && count($duplicate_key_list) > 0) {
368                                                 foreach ($duplicate_key_list as $k) {
369                                                         return Ethna::raiseNotice('½ÅÊ£¥¨¥é¡¼[%s]', E_APP_DUPENT, $k);
370                                                 }
371                                         }
372                                 } else {
373                                         return $r;
374                                 }
375                         } else {
376                                 break;
377                         }
378                 }
379                 if ($i == 4) {
380                         // cannot be reached
381                         return Ethna::raiseError('½ÅÊ£¥¨¥é¡¼¥­¡¼È½ÊÌ¥¨¥é¡¼', E_GENERAL);
382                 }
383
384                 $this->prop_backup = $this->prop;
385
386                 // ID¤Î¼èÆÀ(MySQL¤Î¤ßÂбþ)
387                 if ($this->my_db_rw->getType() == 'mysql') {
388                         // MySQL¤ÎAUTO_INCREMENT¤Ï¥Æ¡¼¥Ö¥ë¤Ë1¥«¥é¥à¤Ç³î¤ÄPRIMARY KEY
389                         foreach (to_array($this->id_def) as $id_def) {
390                                 if ($this->prop_def[$id_def]['seq']) {
391                                         $this->prop[$id_def] = $this->my_db_rw->getInsertId();
392                                         break;
393                                 }
394                         }
395                 }
396
397                 // ID¤ÎÀßÄê
398                 if (is_array($this->id_def)) {
399                         $this->id = array();
400                         foreach ($this->id_def as $k) {
401                                 $this->id[] = $this->prop[$k];
402                         }
403                 } else {
404                         $this->id = $this->prop[$this->id_def];
405                 }
406
407                 $this->prop_backup = $this->prop;
408
409                 return 0;
410         }
411
412         /**
413          *      ¥ª¥Ö¥¸¥§¥¯¥È¤ò¹¹¿·¤¹¤ë
414          *
415          *      @access public
416          *      @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
417          */
418         function update()
419         {
420                 $sql = $this->_getSQL_Update();
421                 for ($i = 0; $i < 4; $i++) {
422                         $r =& $this->my_db_rw->query($sql);
423                         if (Ethna::isError($r)) {
424                                 if ($r->getCode() == E_DB_DUPENT) {
425                                         // ½ÅÊ£¥¨¥é¡¼¥­¡¼¤ÎȽÊÌ
426                                         $duplicate_key_list = $this->_getDuplicateKeyList();
427                                         if (Ethna::isError($duplicate_key_list)) {
428                                                 return $duplicate_key_list;
429                                         }
430                                         if (is_array($duplicate_key_list) && count($duplicate_key_list) > 0) {
431                                                 foreach ($duplicate_key_list as $k) {
432                                                         return Ethna::raiseNotice('½ÅÊ£¥¨¥é¡¼[%s]', E_APP_DUPENT, $k);
433                                                 }
434                                         }
435                                 } else {
436                                         return $r;
437                                 }
438                         } else {
439                                 break;
440                         }
441                 }
442                 if ($i == 4) {
443                         // cannot be reached
444                         return Ethna::raiseError('½ÅÊ£¥¨¥é¡¼¥­¡¼È½ÊÌ¥¨¥é¡¼', E_GENERAL);
445                 }
446
447                 $affected_rows = $this->my_db_rw->affectedRows();
448                 if ($affected_rows <= 0) {
449                         $this->backend->log(LOG_DEBUG, "update query with 0 updated rows");
450                 }
451
452                 // ¥Ð¥Ã¥¯¥¢¥Ã¥×/¥­¥ã¥Ã¥·¥å¹¹¿·
453                 $this->prop_backup = $this->prop;
454                 $this->_clearPropCache();
455
456                 return 0;
457         }
458
459         /**
460          *      ¥ª¥Ö¥¸¥§¥¯¥È¤òÃÖ´¹¤¹¤ë
461          *
462          *      MySQL¤ÎREPLACEʸ¤ËÁêÅö¤¹¤ëÆ°ºî¤ò¹Ô¤¦(add()¤Ç½ÅÊ£¥¨¥é¡¼¤¬È¯À¸¤·¤¿¤é
463          *      update()¤ò¹Ô¤¦)
464          *
465          *      @access public
466          *      @return mixed   0:Àµ¾ï½ªÎ» >0:¥ª¥Ö¥¸¥§¥¯¥ÈID(Äɲûþ) Ethna_Error:¥¨¥é¡¼
467          */
468         function replace()
469         {
470                 $sql = $this->_getSQL_Select($this->getIdDef(), $this->getId());
471
472                 for ($i = 0; $i < 3; $i++) {
473                         $r = $this->my_db_rw->query($sql);
474                         if (Ethna::isError($r)) {
475                                 return $r;
476                         }
477                         $n = $r->numRows();
478
479                         if ($n > 0) {
480                                 $r = $this->update();
481                                 return $r;
482                         } else {
483                                 $r = $this->add();
484                                 if (Ethna::isError($r) == false) {
485                                         return $r;
486                                 } else if ($r->getCode() != E_APP_DUPENT) {
487                                         return $r;
488                                 }
489                         }
490                 }
491                 
492                 return $r;
493         }
494
495         /**
496          *      ¥ª¥Ö¥¸¥§¥¯¥È¤òºï½ü¤¹¤ë
497          *
498          *      @access public
499          *      @return mixed   0:Àµ¾ï½ªÎ» Ethna_Error:¥¨¥é¡¼
500          */
501         function remove()
502         {
503                 $sql = $this->_getSQL_Remove();
504                 $r =& $this->my_db_rw->query($sql);
505                 if (Ethna::isError($r)) {
506                         return $r;
507                 }
508
509                 // ¥×¥í¥Ñ¥Æ¥£/¥Ð¥Ã¥¯¥¢¥Ã¥×/¥­¥ã¥Ã¥·¥å¥¯¥ê¥¢
510                 $this->id = $this->prop = $this->prop_backup = null;
511                 $this->_clearPropCache();
512
513                 return 0;
514         }
515
516         /**
517          *      ¥ª¥Ö¥¸¥§¥¯¥ÈID¤ò¸¡º÷¤¹¤ë
518          *
519          *      @access public
520          *      @param  array   $filter         ¸¡º÷¾ò·ï
521          *      @param  array   $order          ¸¡º÷·ë²Ì¥½¡¼¥È¾ò·ï
522          *      @param  int             $offset         ¸¡º÷·ë²Ì¼èÆÀ¥ª¥Õ¥»¥Ã¥È
523          *      @param  int             $count          ¸¡º÷·ë²Ì¼èÆÀ¿ô
524          *      @return mixed   array(0 => ¸¡º÷¾ò·ï¤Ë¥Þ¥Ã¥Á¤·¤¿·ï¿ô, 1 => $offset, $count¤Ë¤è¤ê»ØÄꤵ¤ì¤¿·ï¿ô¤Î¥ª¥Ö¥¸¥§¥¯¥ÈID°ìÍ÷) Ethna_Error:¥¨¥é¡¼
525          */
526         function searchId($filter = null, $order = null, $offset = null, $count = null)
527         {
528                 if (is_null($filter) == false) {
529                         $sql = $this->_getSQL_SearchLength($filter);
530                         $r =& $this->my_db_ro->query($sql);
531                         if (Ethna::isError($r)) {
532                                 return $r;
533                         }
534                         $row = $r->fetchRow(DB_FETCHMODE_ASSOC);
535                         $length = $row['id_count'];
536                 } else {
537                         $length = null;
538                 }
539
540                 $id_list = array();
541                 $sql = $this->_getSQL_SearchId($filter, $order, $offset, $count);
542                 $r =& $this->my_db_ro->query($sql);
543                 if (Ethna::isError($r)) {
544                         return $r;
545                 }
546                 $n = $r->numRows();
547                 for ($i = 0; $i < $n; $i++) {
548                         $row = $r->fetchRow(DB_FETCHMODE_ASSOC);
549
550                         // ¥×¥é¥¤¥Þ¥ê¥­¡¼¤¬1¥«¥é¥à¤Ê¤é¥¹¥«¥é¡¼ÃͤËÊÑ´¹
551                         if (is_array($this->id_def) == false) {
552                                 $row = $row[$this->id_def];
553                         }
554                         $id_list[] = $row;
555                 }
556                 if (is_null($length)) {
557                         $length = count($id_list);
558                 }
559
560                 return array($length, $id_list);
561         }
562
563         /**
564          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò¸¡º÷¤¹¤ë
565          *
566          *      @access public
567          *      @param  array   $keys           ¼èÆÀ¤¹¤ë¥×¥í¥Ñ¥Æ¥£
568          *      @param  array   $filter         ¸¡º÷¾ò·ï
569          *      @param  array   $order          ¸¡º÷·ë²Ì¥½¡¼¥È¾ò·ï
570          *      @param  int             $offset         ¸¡º÷·ë²Ì¼èÆÀ¥ª¥Õ¥»¥Ã¥È
571          *      @param  int             $count          ¸¡º÷·ë²Ì¼èÆÀ¿ô
572          *      @return mixed   array(0 => ¸¡º÷¾ò·ï¤Ë¥Þ¥Ã¥Á¤·¤¿·ï¿ô, 1 => $offset, $count¤Ë¤è¤ê»ØÄꤵ¤ì¤¿·ï¿ô¤Î¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£°ìÍ÷) Ethna_Error:¥¨¥é¡¼
573          */
574         function searchProp($keys = null, $filter = null, $order = null, $offset = null, $count = null)
575         {
576                 if (is_null($filter) == false) {
577                         $sql = $this->_getSQL_SearchLength($filter);
578                         $r =& $this->my_db_ro->query($sql);
579                         if (Ethna::isError($r)) {
580                                 return $r;
581                         }
582                         $row = $r->fetchRow(DB_FETCHMODE_ASSOC);
583                         $length = $row['id_count'];
584                 } else {
585                         $length = null;
586                 }
587
588                 $prop_list = array();
589                 $sql = $this->_getSQL_SearchProp($keys, $filter, $order, $offset, $count);
590                 $r =& $this->my_db_ro->query($sql);
591                 if (Ethna::isError($r)) {
592                         return $r;
593                 }
594                 $n = $r->numRows();
595                 for ($i = 0; $i < $n; $i++) {
596                         $row = $r->fetchRow(DB_FETCHMODE_ASSOC);
597                         $prop_list[] = $row;
598                 }
599                 if (is_null($length)) {
600                         $length = count($prop_list);
601                 }
602
603                 return array($length, $prop_list);
604         }
605
606         /**
607          *      ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ç¥Õ¥©¥ë¥È¥×¥í¥Ñ¥Æ¥£¤òÀßÄꤹ¤ë
608          *
609          *      ¥³¥ó¥¹¥È¥é¥¯¥¿¤Ë¤è¤ê»ØÄꤵ¤ì¤¿¥­¡¼¤Ë¥Þ¥Ã¥Á¤¹¤ë¥¨¥ó¥È¥ê¤¬¤Ê¤«¤Ã¤¿¾ì¹ç¤Î
610          *      ¥Ç¥Õ¥©¥ë¥È¥×¥í¥Ñ¥Æ¥£¤ò¤³¤³¤ÇÀßÄꤹ¤ë¤³¤È¤¬½ÐÍè¤ë
611          *
612          *      @access protected
613          *      @param  mixed   $key_type       ¸¡º÷¥­¡¼Ì¾
614          *      @param  mixed   $key            ¸¡º÷¥­¡¼
615          *      @return int             0:Àµ¾ï½ªÎ»
616          */
617         function _setDefault($key_type, $key)
618         {
619                 return 0;
620         }
621
622         /**
623          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤òDB¤«¤é¼èÆÀ¤¹¤ë
624          *
625          *      @access private
626          *      @param  mixed   $key_type       ¸¡º÷¥­¡¼Ì¾
627          *      @param  mixed   $key            ¸¡º÷¥­¡¼
628          */
629         function _setPropByDB($key_type, $key)
630         {
631                 global $_ETHNA_APP_OBJECT_CACHE;
632
633                 $key_type = to_array($key_type);
634                 $key = to_array($key);
635                 if (count($key_type) != count($key)) {
636                         trigger_error(sprintf("Unmatched key_type & key length [%d-%d]", count($key_type), count($key)), E_USER_ERROR);
637                         return;
638                 }
639                 foreach ($key_type as $elt) {
640                         if (isset($this->prop_def[$elt]) == false) {
641                                 trigger_error("Invalid key_type [$elt]", E_USER_ERROR);
642                                 return;
643                         }
644                 }
645
646                 // ¥­¥ã¥Ã¥·¥å¥Á¥§¥Ã¥¯
647                 $class_name = strtolower(get_class($this));
648                 if (is_array($_ETHNA_APP_OBJECT_CACHE) == false || array_key_exists($class_name, $_ETHNA_APP_OBJECT_CACHE) == false) {
649                         $_ETHNA_APP_OBJECT_CACHE[$class_name] = array();
650                 }
651                 $cache_key = serialize(array($key_type, $key));
652                 if (array_key_exists($cache_key, $_ETHNA_APP_OBJECT_CACHE[$class_name])) {
653                         $this->prop = $_ETHNA_APP_OBJECT_CACHE[$class_name][$cache_key];
654                         return;
655                 }
656
657                 // SQLʸ¹½ÃÛ
658                 $sql = $this->_getSQL_Select($key_type, $key);
659
660                 // ¥×¥í¥Ñ¥Æ¥£¼èÆÀ
661                 $r =& $this->my_db_ro->query($sql);
662                 if (Ethna::isError($r)) {
663                         return;
664                 }
665                 $n = $r->numRows();
666                 if ($n == 0) {
667                         // try default
668                         if ($this->_setDefault($key_type, $key) == false) {
669                                 // nop
670                         }
671                         return;
672                 } else if ($n > 1) {
673                         trigger_error("Invalid key (multiple rows found) [$key]", E_USER_ERROR);
674                         return;
675                 }
676                 $this->prop = $r->fetchRow(DB_FETCHMODE_ASSOC);
677
678                 // ¥­¥ã¥Ã¥·¥å¥¢¥Ã¥×¥Ç¡¼¥È
679                 $_ETHNA_APP_OBJECT_CACHE[$class_name][$cache_key] = $this->prop;
680         }
681
682         /**
683          *      ¥³¥ó¥¹¥È¥é¥¯¥¿¤Ç»ØÄꤵ¤ì¤¿¥×¥í¥Ñ¥Æ¥£¤òÀßÄꤹ¤ë
684          *
685          *      @access private
686          *      @param  array   $prop   ¥×¥í¥Ñ¥Æ¥£°ìÍ÷
687          */
688         function _setPropByValue($prop)
689         {
690                 $def = $this->getDef();
691                 foreach ($def as $key => $value) {
692                         if ($value['primary'] && isset($prop[$key]) == false) {
693                                 // ¥×¥é¥¤¥Þ¥ê¥­¡¼¤Ï¾ÊάÉÔ²Ä
694                                 trigger_error("primary key is not identical", E_USER_ERROR);
695                         }
696                         $this->prop[$key] = $prop[$key];
697                 }
698         }
699
700         /**
701          *      ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥×¥é¥¤¥Þ¥ê¥Æ¡¼¥Ö¥ë¤ò¼èÆÀ¤¹¤ë
702          *
703          *      @access private
704          *      @return string  ¥ª¥Ö¥¸¥§¥¯¥È¤Î¥×¥é¥¤¥Þ¥ê¥Æ¡¼¥Ö¥ë̾
705          */
706         function _getPrimaryTable()
707         {
708                 $tables = array_keys($this->table_def);
709                 $table = $tables[0];
710                 
711                 return $table;
712         }
713
714         /**
715          *      ½ÅÊ£¥­¡¼¤ò¼èÆÀ¤¹¤ë
716          *
717          *      @access private
718          *      @return mixed   0:½ÅÊ£¤Ê¤· Ethna_Error:¥¨¥é¡¼ array:½ÅÊ£¥­¡¼¤Î¥×¥í¥Ñ¥Æ¥£Ì¾°ìÍ÷
719          */
720         function _getDuplicateKeyList()
721         {
722                 $duplicate_key_list = array();
723
724                 // ¸½ºßÀßÄꤵ¤ì¤Æ¤¤¤ë¥×¥é¥¤¥Þ¥ê¥­¡¼¤ËNULL¤¬´Þ¤Þ¤ì¤ë¾ì¹ç¤Ï¸¡º÷¤·¤Ê¤¤
725                 $check_pkey = true;
726                 foreach (to_array($this->id_def) as $k) {
727                         if (isset($this->prop[$k]) == false || is_null($this->prop[$k])) {
728                                 $check_pkey = false;
729                                 break;
730                         }
731                 }
732
733                 // ¥×¥é¥¤¥Þ¥ê¥­¡¼¤Ïmulti columns¤Ë¤Ê¤êÆÀ¤ë¤Î¤ÇÊÌ°·¤¤
734                 if ($check_pkey) {
735                         $sql = $this->_getSQL_Duplicate($this->id_def);
736                         $r =& $this->my_db_rw->query($sql);
737                         if (Ethna::isError($r)) {
738                                 return $r;
739                         } else if ($r->numRows() > 0) {
740                                 $duplicate_key_list = to_array($this->id_def); // we can overwrite $key_list here
741                         }
742                 }
743
744                 // ¥æ¥Ë¡¼¥¯¥­¡¼
745                 foreach ($this->prop_def as $k => $v) {
746                         if ($v['primary'] == true || $v['key'] == false) {
747                                 continue;
748                         }
749                         $sql = $this->_getSQL_Duplicate($k);
750                         $r =& $this->my_db_rw->query($sql);
751                         if (Ethna::isError($r)) {
752                                 return $r;
753                         } else if ($r->NumRows() > 0) {
754                                 $duplicate_key_list[] = $k;
755                         }
756                 }
757
758                 if (count($duplicate_key_list) > 0) {
759                         return $duplicate_key_list;
760                 } else {
761                         return 0;
762                 }
763         }
764
765         /**
766          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò¼èÆÀ¤¹¤ëSQLʸ¤ò¹½ÃÛ¤¹¤ë
767          *
768          *      @access private
769          *      @param  array   $key_type       ¥­¡¼¤È¤Ê¤ë¥×¥í¥Ñ¥Æ¥£Ì¾°ìÍ÷
770          *      @param  array   $key            $key_type¤ËÂбþ¤¹¤ë¥­¡¼°ìÍ÷
771          *      @return string  SELECTʸ
772          */
773         function _getSQL_Select($key_type, $key)
774         {
775                 $key_type = to_array($key_type);
776                 if (is_null($key)) {
777                         // add()Á°
778                         $key = array();
779                         for ($i = 0; $i < count($key_type); $i++) {
780                                 $key[$i] = null;
781                         }
782                 } else {
783                         $key = to_array($key);
784                 }
785
786                 // SQL¥¨¥¹¥±¡¼¥×
787                 Ethna_AppSQL::escapeSQL($key);
788
789                 $tables = implode(',', array_keys($this->table_def));
790                 $columns = implode(',', array_keys($this->prop_def));
791
792                 // ¸¡º÷¾ò·ï
793                 $condition = null;
794                 for ($i = 0; $i < count($key_type); $i++) {
795                         if (is_null($condition)) {
796                                 $condition = "WHERE ";
797                         } else {
798                                 $condition .= " AND ";
799                         }
800                         $condition .= Ethna_AppSQL::getCondition($key_type[$i], $key[$i]);
801                 }
802
803                 $sql = "SELECT $columns FROM $tables $condition";
804
805                 return $sql;
806         }
807
808         /**
809          *      ¥ª¥Ö¥¸¥§¥¯¥È¤ÈÄɲ乤ëSQLʸ¤ò¹½ÃÛ¤¹¤ë
810          *
811          *      @access private
812          *      @return string  ¥ª¥Ö¥¸¥§¥¯¥È¤òÄɲ乤뤿¤á¤ÎINSERTʸ
813          */
814         function _getSQL_Add()
815         {
816                 $tables = implode(',', array_keys($this->table_def));
817
818                 // SET¶ç¹½ÃÛ
819                 $set_list = "";
820                 $prop_arg_list = $this->prop;
821                 Ethna_AppSQL::escapeSQL($prop_arg_list);
822                 foreach ($this->prop_def as $k => $v) {
823                         if (isset($prop_arg_list[$k]) == false) {
824                                 continue;
825                         }
826                         if ($set_list != "") {
827                                 $set_list .= ",";
828                         }
829                         $set_list .= sprintf("%s=%s", $k, $prop_arg_list[$k]);
830                 }
831
832                 $sql = "INSERT INTO $tables SET $set_list";
833
834                 return $sql;
835         }
836
837         /**
838          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò¹¹¿·¤¹¤ëSQLʸ¤ò¹½ÃÛ¤¹¤ë
839          *
840          *      @access private
841          *      @return ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤ò¹¹¿·¤¹¤ë¤¿¤á¤ÎUPDATEʸ
842          */
843         function _getSQL_Update()
844         {
845                 $tables = implode(',', array_keys($this->table_def));
846
847                 // SET¶ç¹½ÃÛ
848                 $set_list = "";
849                 $prop_arg_list = $this->prop;
850                 Ethna_AppSQL::escapeSQL($prop_arg_list);
851                 foreach ($this->prop_def as $k => $v) {
852                         if ($set_list != "") {
853                                 $set_list .= ",";
854                         }
855                         $set_list .= sprintf("%s=%s", $k, $prop_arg_list[$k]);
856                 }
857
858                 // ¸¡º÷¾ò·ï(primary key)
859                 $condition = null;
860                 foreach (to_array($this->id_def) as $k) {
861                         if (is_null($condition)) {
862                                 $condition = "WHERE ";
863                         } else {
864                                 $condition .= " AND ";
865                         }
866                         $v = $this->prop_backup[$k];    // equals to $this->id
867                         Ethna_AppSQL::escapeSQL($v);
868                         $condition .= Ethna_AppSQL::getCondition($k, $v);
869                 }
870
871                 $sql = "UPDATE $tables SET $set_list $condition";
872
873                 return $sql;
874         }
875
876         /**
877          *      ¥ª¥Ö¥¸¥§¥¯¥È¤òºï½ü¤¹¤ëSQLʸ¤ò¹½ÃÛ¤¹¤ë
878          *
879          *      @access private
880          *      @return string  ¥ª¥Ö¥¸¥§¥¯¥È¤òºï½ü¤¹¤ë¤¿¤á¤ÎDELETEʸ
881          */
882         function _getSQL_Remove()
883         {
884                 $tables = implode(',', array_keys($this->table_def));
885
886                 // ¸¡º÷¾ò·ï(primary key)
887                 $condition = null;
888                 foreach (to_array($this->id_def) as $k) {
889                         if (is_null($condition)) {
890                                 $condition = "WHERE ";
891                         } else {
892                                 $condition = " AND ";
893                         }
894                         $v = $this->prop_backup[$k];    // equals to $this->id
895                         Ethna_AppSQL::escapeSQL($v);
896                         $condition .= Ethna_AppSQL::getCondition($k, $v);
897                 }
898                 if (is_null($condition)) {
899                         trigger_error("DELETE with no conditon", E_USER_ERROR);
900                         return null;
901                 }
902
903                 $sql = "DELETE FROM $tables $condition";
904
905                 return $sql;
906         }
907
908         /**
909          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤Î¥æ¥Ë¡¼¥¯¥Á¥§¥Ã¥¯¤ò¹Ô¤¦SQLʸ¤ò¹½ÃÛ¤¹¤ë
910          *
911          *      @access private
912          *      @param  mixed   $key    ¥æ¥Ë¡¼¥¯¥Á¥§¥Ã¥¯¤ò¹Ô¤¦¥×¥í¥Ñ¥Æ¥£Ì¾
913          *      @return string  ¥æ¥Ë¡¼¥¯¥Á¥§¥Ã¥¯¤ò¹Ô¤¦¤¿¤á¤ÎSELECTʸ
914          */
915         function _getSQL_Duplicate($key)
916         {
917                 $tables = implode(',', array_keys($this->table_def));
918                 $columns = implode(',', array_keys($this->prop_def));   // any column will do
919
920                 $condition = null;
921                 // ¸¡º÷¾ò·ï(¸½ºßÀßÄꤵ¤ì¤Æ¤¤¤ë¥×¥é¥¤¥Þ¥ê¥­¡¼¤Ï¸¡º÷Âоݤ«¤é½ü¤¯)
922                 if (is_null($this->id) == false) {
923                         $primary_value = to_array($this->getId());
924                         $n = 0;
925                         foreach (to_array($this->id_def) as $k) {
926                                 if (is_null($condition)) {
927                                         $condition = "WHERE ";
928                                 } else {
929                                         $condition .= " AND ";
930                                 }
931                                 $value = $primary_value[$n];
932                                 Ethna_AppSQL::escapeSQL($value);
933                                 $condition .= Ethna_AppSQL::getCondition($k, $value, OBJECT_CONDITION_NE);
934                                 $n++;
935                         }
936                 }
937
938                 foreach (to_array($key) as $k) {
939                         if (is_null($condition)) {
940                                 $condition = "WHERE ";
941                         } else {
942                                 $condition .= " AND ";
943                         }
944                         $v = $this->prop[$k];
945                         Ethna_AppSQL::escapeSQL($v);
946                         $condition .= Ethna_AppSQL::getCondition($k, $v);
947                 }
948
949                 $sql = "SELECT $columns FROM $tables $condition";
950
951                 return $sql;
952         }
953
954         /**
955          *      ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷Áí¿ô(offset, count½ü³°)¤ò¼èÆÀ¤¹¤ëSQLʸ¤ò¹½ÃÛ¤¹¤ë
956          *
957          *      @access private
958          *      @param  array   $filter         ¸¡º÷¾ò·ï
959          *      @return string  ¸¡º÷Áí¿ô¤ò¼èÆÀ¤¹¤ë¤¿¤á¤ÎSELECTʸ
960          */
961         function _getSQL_SearchLength($filter)
962         {
963                 // ¥Æ¡¼¥Ö¥ë
964                 $tables = implode(',', array_keys($this->table_def));
965                 if ($this->_isAdditionalField($filter)) {
966                         $tables .= " " . $this->_SQLPlugin_SearchTable();
967                 }
968
969                 $id_def = to_array($this->id_def);
970                 $column_id = $this->_getPrimaryTable() . "." . $id_def[0];      // any id columns will do
971
972                 $condition = $this->_getSQL_SearchCondition($filter);
973                 $sql = "SELECT COUNT(DISTINCT $column_id) AS id_count FROM $tables $condition";
974
975                 return $sql;
976         }
977
978         /**
979          *      ¥ª¥Ö¥¸¥§¥¯¥ÈID¸¡º÷¤ò¹Ô¤¦SQLʸ¤ò¹½ÃÛ¤¹¤ë
980          *
981          *      @access private
982          *      @param  array   $filter         ¸¡º÷¾ò·ï
983          *      @param  array   $order          ¸¡º÷·ë²Ì¥½¡¼¥È¾ò·ï
984          *      @param  int             $offset         ¸¡º÷·ë²Ì¼èÆÀ¥ª¥Õ¥»¥Ã¥È
985          *      @param  int             $count          ¸¡º÷·ë²Ì¼èÆÀ¿ô
986          *      @return string  ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷¤ò¹Ô¤¦SELECTʸ
987          */
988         function _getSQL_SearchId($filter, $order, $offset, $count)
989         {
990                 // ¥Æ¡¼¥Ö¥ë
991                 $tables = implode(',', array_keys($this->table_def));
992                 if ($this->_isAdditionalField($filter) || $this->_isAdditionalField($order)) {
993                         $tables .= " " . $this->_SQLPlugin_SearchTable();
994                 }
995
996                 $column_id = "";
997                 foreach (to_array($this->id_def) as $id) {
998                         if ($column_id != "") {
999                                 $column_id .= ",";
1000                         }
1001                         $column_id .= $this->_getPrimaryTable() . "." . $id;
1002                 }
1003                 $condition = $this->_getSQL_SearchCondition($filter);
1004
1005                 $sort = "";
1006                 if (is_array($order)) {
1007                         foreach ($order as $k => $v) {
1008                                 if ($sort == "") {
1009                                         $sort = "ORDER BY ";
1010                                 } else {
1011                                         $sort .= ", ";
1012                                 }
1013                                 $sort .= sprintf("%s %s", $k, $v == OBJECT_SORT_ASC ? "ASC" : "DESC");
1014                         }
1015                 }
1016
1017                 $limit = "";
1018                 if (is_null($count) == false) {
1019                         $limit = "LIMIT ";
1020                         if (is_null($offset) == false) {
1021                                 $limit .= sprintf("%d,", $offset);
1022                         }
1023                         $limit .= sprintf("%d", $count);
1024                 }
1025
1026                 $sql = "SELECT DISTINCT $column_id FROM $tables $condition $sort $limit";
1027
1028                 return $sql;
1029         }
1030
1031         /**
1032          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¸¡º÷¤ò¹Ô¤¦SQLʸ¤ò¹½ÃÛ¤¹¤ë
1033          *
1034          *      @access private
1035          *      @param  array   $keys           ¼èÆÀ¥×¥í¥Ñ¥Æ¥£°ìÍ÷
1036          *      @param  array   $filter         ¸¡º÷¾ò·ï
1037          *      @param  array   $order          ¸¡º÷·ë²Ì¥½¡¼¥È¾ò·ï
1038          *      @param  int             $offset         ¸¡º÷·ë²Ì¼èÆÀ¥ª¥Õ¥»¥Ã¥È
1039          *      @param  int             $count          ¸¡º÷·ë²Ì¼èÆÀ¿ô
1040          *      @return string  ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷¤ò¹Ô¤¦SELECTʸ
1041          */
1042         function _getSQL_SearchProp($keys, $filter, $order, $offset, $count)
1043         {
1044                 // ¥Æ¡¼¥Ö¥ë
1045                 $tables = implode(',', array_keys($this->table_def));
1046                 if ($this->_isAdditionalField($filter) || $this->_isAdditionalField($order)) {
1047                         $tables .= " " . $this->_SQLPlugin_SearchTable();
1048                 }
1049                 $p_table = $this->_getPrimaryTable();
1050
1051                 // ¸¡º÷ÍÑÄɲåץí¥Ñ¥Æ¥£
1052                 if ($this->_isAdditionalField($filter) || $this->_isAdditionalField($order)) {
1053                         $search_prop_def = $this->_SQLPlugin_SearchPropDef();
1054                 } else {
1055                         $search_prop_def = array();
1056                 }
1057                 $def = array_merge($this->getDef(), $search_prop_def);
1058
1059                 // ¥«¥é¥à
1060                 $column = "";
1061                 $group_by = "";
1062                 if (is_null($keys)) {
1063                         $keys = array_keys($def);
1064                 }
1065                 foreach (to_array($keys) as $key) {
1066                         if (isset($def[$key]) == false) {
1067                                 continue;
1068                         }
1069                         if ($column != "") {
1070                                 $column .= ", ";
1071                         }
1072                         $t = isset($def[$key]['table']) ? $def[$key]['table'] : $p_table;
1073                         $column .= sprintf("%s.%s", $t, $key);
1074
1075                         // ¥Õ¥£¡¼¥ë¥É¤¬¥×¥é¥¤¥Þ¥ê¡¼¥­¡¼¤Ê¤éGROUP BY¤¹¤ë
1076                         if ((isset($def[$key]['table']) && $def[$key]['table'] == $p_table) ||
1077                                 isset($def[$key]['table']) == false) {
1078                                 if ($def[$key]['primary']) {
1079                                         if ($group_by != "") {
1080                                                 $group_by .= ",";
1081                                         } else {
1082                                                 $group_by .= "GROUP BY";
1083                                         }
1084                                         $group_by .= " $column";
1085                                 }
1086                         }
1087                 }
1088
1089                 $condition = $this->_getSQL_SearchCondition($filter);
1090
1091                 $sort = "";
1092                 if (is_array($order)) {
1093                         foreach ($order as $k => $v) {
1094                                 if ($sort == "") {
1095                                         $sort = "ORDER BY ";
1096                                 } else {
1097                                         $sort .= ", ";
1098                                 }
1099                                 $sort .= sprintf("%s %s", $k, $v == OBJECT_SORT_ASC ? "ASC" : "DESC");
1100                         }
1101                 }
1102
1103                 $limit = "";
1104                 if (is_null($count) == false) {
1105                         $limit = "LIMIT ";
1106                         if (is_null($offset) == false) {
1107                                 $limit .= sprintf("%d,", $offset);
1108                         }
1109                         $limit .= sprintf("%d", $count);
1110                 }
1111
1112                 $sql = "SELECT $column FROM $tables $condition $group_by $sort $limit";
1113
1114                 return $sql;
1115         }
1116
1117         /**
1118          *      ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷SQL¤Î¾ò·ïʸ¤ò¹½ÃÛ¤¹¤ë
1119          *
1120          *      @access private
1121          *      @param  array   $filter         ¸¡º÷¾ò·ï
1122          *      @return string  ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷¤Î¾ò·ïʸ(¥¨¥é¡¼¤Ê¤énull)
1123          */
1124         function _getSQL_SearchCondition($filter)
1125         {
1126                 if (is_array($filter) == false) {
1127                         return "";
1128                 }
1129
1130                 $p_table = $this->_getPrimaryTable();
1131
1132                 // ¸¡º÷ÍÑÄɲåץí¥Ñ¥Æ¥£
1133                 if ($this->_isAdditionalField($filter)) {
1134                         $search_prop_def = $this->_SQLPlugin_SearchPropDef();
1135                 } else {
1136                         $search_prop_def = array();
1137                 }
1138                 $prop_def = array_merge($this->prop_def, $search_prop_def);
1139
1140                 $condition = null;
1141                 foreach ($filter as $k => $v) {
1142                         if (isset($prop_def[$k]) == false) {
1143                                 trigger_error(sprintf("Unknown property [%s]", $k), E_USER_ERROR);
1144                                 return null;
1145                         }
1146
1147                         if (is_null($condition)) {
1148                                 $condition = "WHERE ";
1149                         } else {
1150                                 $condition .= " AND ";
1151                         }
1152
1153                         $t = isset($prop_def[$k]['table']) ? $prop_def[$k]['table'] : $p_table;
1154
1155                         if (is_object($v)) {
1156                                 // Ethna_AppSearchObject¤¬»ØÄꤵ¤ì¤Æ¤¤¤ë¾ì¹ç
1157                                 $condition .= $v->toString("$t.$k");
1158                         } else if (is_array($v) && count($v) > 0 && is_object($v[0])) {
1159                                 // Ethna_AppSearchObject¤¬ÇÛÎó¤Ç»ØÄꤵ¤ì¤Æ¤¤¤ë¾ì¹ç
1160                                 $n = 0;
1161                                 foreach ($v as $so) {
1162                                         if ($n > 0) {
1163                                                 $condition .= " AND ";
1164                                         }
1165                                         $condition .= $so->toStrong("$t.$k");
1166                                         $n++;
1167                                 }
1168                         } else if ($prop_def[$k]['type'] == VAR_TYPE_STRING) {
1169                                 // ¾Êά·Á(ʸ»úÎó)
1170                                 Ethna_AppSQL::escapeSQL($v);
1171                                 $condition .= Ethna_AppSQL::getCondition("$t.$k", $v, OBJECT_CONDITION_LIKE);
1172                         } else {
1173                                 // ¾Êά·Á(¿ôÃÍ)
1174                                 Ethna_AppSQL::escapeSQL($v);
1175                                 $condition .= Ethna_AppSQL::getCondition("$t.$k", $v, OBJECT_CONDITION_EQ);
1176                         }
1177                 }
1178
1179                 return $condition;
1180         }
1181
1182         /**
1183          *      ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷SQL¥×¥é¥°¥¤¥ó(Äɲåơ¼¥Ö¥ë)
1184          *
1185          *      sample:
1186          *      <code>
1187          *      return " LEFT JOIN bar_tbl ON foo_tbl.user_id=bar_tbl.user_id";
1188          *      </code>
1189          *
1190          *      @access protected
1191          *      @return string  ¥Æ¡¼¥Ö¥ëJOIN¤ÎSQLʸ
1192          */
1193         function _SQLPlugin_SearchTable()
1194         {
1195                 return "";
1196         }
1197
1198         /**
1199          *      ¥ª¥Ö¥¸¥§¥¯¥È¸¡º÷SQL¥×¥é¥°¥¤¥ó(Äɲþò·ïÄêµÁ)
1200          *
1201          *      sample:
1202          *      <code>
1203          *      $search_prop_def = array(
1204          *        'group_id' => array(
1205          *          'primary' => true, 'key' => true, 'type' => VAR_TYPE_INT,
1206          *          'form_name' => 'group_id', 'table' => 'group_user_tbl',
1207          *        ),
1208          *      );
1209          *      return $search_prop_def;
1210          *      </code>
1211          *
1212          *      @access protected
1213          *      @return array   Äɲþò·ïÄêµÁ
1214          */
1215         function _SQLPlugin_SearchPropDef()
1216         {
1217         }
1218
1219         /**
1220          *      ¥ª¥Ö¥¸¥§¥¯¥È¥×¥í¥Ñ¥Æ¥£¤òCSV·Á¼°¤Ç¥À¥ó¥×¤¹¤ë
1221          *
1222          *      @access protected
1223          *      @return string  ¥À¥ó¥×·ë²Ì
1224          */
1225         function _dump_csv()
1226         {
1227                 $dump = "";
1228
1229                 $n = 0;
1230                 foreach ($this->getDef() as $k => $def) {
1231                         if ($n > 0) {
1232                                 $dump .= ",";
1233                         }
1234                         $dump .= Ethna_Util::escapeCSV($this->getName($k));
1235                         $n++;
1236                 }
1237
1238                 return $dump;
1239         }
1240
1241         /**
1242          *      (¸¡º÷¾ò·ï|¥½¡¼¥È¾ò·ï)¥Õ¥£¡¼¥ë¥É¤ËÄɲåե£¡¼¥ë¥É¤¬´Þ¤Þ¤ì¤ë¤«¤É¤¦¤«¤òÊÖ¤¹
1243          *
1244          *      @access private
1245          *      @param  array   $field  (¸¡º÷¾ò·ï|¥½¡¼¥È¾ò·ï)ÄêµÁ
1246          *      @return bool    true:´Þ¤Þ¤ì¤ë false:´Þ¤Þ¤ì¤Ê¤¤
1247          */
1248         function _isAdditionalField($field)
1249         {
1250                 if (is_array($field) == false) {
1251                         return false;
1252                 }
1253
1254                 $def = $this->getDef();
1255                 foreach ($field as $key => $value) {
1256                         if (array_key_exists($key, $def) == false) {
1257                                 return true;
1258                         }
1259                 }
1260                 return false;
1261         }
1262
1263         /**
1264          *      ¥­¥ã¥Ã¥·¥å¥Ç¡¼¥¿¤òºï½ü¤¹¤ë
1265          *
1266          *      @access private
1267          */
1268         function _clearPropCache()
1269         {
1270                 $class_name = strtolower(get_class($this));
1271                 foreach (array('_ETHNA_APP_OBJECT_CACHE', '_ETHNA_APP_MANAGER_OL_CACHE', '_ETHNA_APP_MANAGER_OPL_CACHE', '_ETHNA_APP_MANAGER_OP_CACHE') as $key) {
1272                         if (array_key_exists($key, $GLOBALS) && array_key_exists($class_name, $GLOBALS[$key])) {
1273                                 unset($GLOBALS[$key][$class_name]);
1274                         }
1275                 }
1276         }
1277 }
1278 // }}}
1279 ?>