/class/AppObject.php
PHP | 1657 lines | 925 code | 161 blank | 571 comment | 242 complexity | db831ea14439b0b6117998303249718e MD5 | raw file
Possible License(s): BSD-3-Clause
- <?php
- // vim: foldmethod=marker
- /**
- * AppObject.php
- *
- * @author Masaki Fujimoto <fujimoto@php.net>
- * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
- * @package Ethna
- * @version $Id: 34811a223f106bb88158be4783391e12bdc8b8f2 $
- */
- // {{{ Ethna_AppObject
- /**
- * ?????????????????????
- *
- * @author Masaki Fujimoto <fujimoto@php.net>
- * @access public
- * @package Ethna
- * @todo ?????????
- * @todo remove dependency on PEAR::DB
- * @todo quoteidentifier ? Ethna_AppSQL ????????
- */
- class Ethna_AppObject
- {
- // {{{ properties
- /**#@+
- * @access private
- */
- /** @protected object Ethna_Backend backend?????? */
- protected $backend;
- /** @protected object Ethna_Config ???????? */
- protected $config;
- /** @protected object Ethna_I18N i18n?????? */
- protected $i18n;
- /** @protected object Ethna_ActionForm ??????????????? */
- protected $action_form;
- /** @protected object Ethna_ActionForm ???????????????(???) */
- protected $af;
- /** @protected object Ethna_Session ??????????? */
- protected $session;
- /** @protected string DB???????? */
- protected $db_prefix = null;
- /** @protected array ???????????DB??????????????*/
- protected $table_def = null;
- /** @protected array ????????????????????????? */
- protected $prop_def = null;
- /** @protected array ?????????????????????? */
- protected $prop = null;
- /** @protected array ?????(??????) */
- protected $prop_backup = null;
- /** @protected int ????????????????(sec) */
- protected $prop_def_cache_lifetime = 86400;
- /** @protected array ????????? */
- protected $id_def = null;
- /** @protected int ??????ID (??????????) */
- protected $id = null;
- /**#@-*/
- // }}}
- // {{{ Ethna_AppObject
- /**
- * Ethna_AppObject???????????
- *
- * @access public
- * @param object Ethna_Backend $backend Ethna_Backend??????
- * @param mixed $key_type ????????????????
- * (?????????????????)
- * @param mixed $key ????????????????
- * @param array $prop ?????(??????)??
- * @return mixed 0:???? -1:??/???????? Ethna_Error:???
- */
- public function __construct($backend, $key_type = null, $key = null, $prop = null)
- {
- $this->backend = $backend;
- $this->config = $backend->getConfig();
- $this->action_form = $backend->getActionForm();
- $this->af = $this->action_form;
- $this->session = $backend->getSession();
- $ctl = $backend->getController();
- // DB?????????
- $db_list = $this->_getDBList();
- if (Ethna::isError($db_list)) {
- return $db_list;
- } else if (is_null($db_list['rw'])) {
- return Ethna::raiseError(
- "Ethna_AppObject????????????????????",
- E_DB_NODSN);
- }
- $this->my_db_rw = $db_list['rw'];
- $this->my_db_ro = $db_list['ro'];
- // XXX: app obj?db type???????????
- $this->my_db_type = $this->my_db_rw->getType();
- // ??????????
- // ???????????????????primary?true
- if (is_null($this->table_def)) {
- $this->table_def = $this->_getTableDef();
- }
- if (is_string($this->table_def)) {
- $this->table_def = array($this->table_def => array('primary' => true));
- }
- // ???????(??????????)????
- // ???????????????????????
- if (is_null($this->prop_def)) {
- $this->prop_def = $this->_getPropDef();
- }
- // ???????????????
- foreach (array_keys($this->prop_def) as $k) {
- if (isset($this->prop_def[$k]['primary']) == false) {
- $this->prop_def[$k]['primary'] = false;
- }
- }
- // ??????????????????
- foreach ($this->prop_def as $k => $v) {
- if ($v['primary'] == false) {
- continue;
- }
- if (is_null($this->id_def)) {
- $this->id_def = $k;
- } else if (is_array($this->id_def)) {
- $this->id_def[] = $k;
- } else { // scalar ???
- $this->id_def = array($this->id_def, $k);
- }
- }
-
- // ?????????
- if (is_null($key_type) && is_null($key) && is_null($prop)) {
- // perhaps for adding object
- return 0;
- }
- // ???????
- // $key_type, $key ???????DB????????????
- // $prop ????????????????
- if (is_null($prop)) {
- $this->_setPropByDB($key_type, $key);
- } else {
- $this->_setPropByValue($prop);
- }
- $this->prop_backup = $this->prop;
- // ?????????????
- if (is_array($this->id_def)) {
- $this->id = array();
- foreach ($this->id_def as $k) {
- $this->id[] = $this->prop[$k];
- }
- } else {
- $this->id = $this->prop[$this->id_def];
- }
- return 0;
- }
- // }}}
- // {{{ isValid
- /**
- * ????????????????
- * ????????????????????????????????
- *
- * @access public
- * @return bool true:?? false:??
- */
- function isValid()
- {
- if (is_array($this->id)) {
- return is_null($this->id[0]) ? false : true;
- } else {
- return is_null($this->id) ? false : true;
- }
- }
- // }}}
- // {{{ isActive
- /**
- * ???????????????????
- *
- * isValid()?????????????????????????????
- * isActive()????????????????????????????
- *
- * @access public
- * @return bool true:????? false:??????
- */
- function isActive()
- {
- if ($this->isValid() == false) {
- return false;
- }
- return $this->prop['state'] == OBJECT_STATE_ACTIVE ? true : false;
- }
- // }}}
- // {{{ getDef
- /**
- * ??????????????(?????)???
- *
- * @access public
- * @return array ??????????????
- */
- function getDef()
- {
- return $this->prop_def;
- }
- // }}}
- // {{{ getIdDef
- /**
- * ????????????
- *
- * @access public
- * @return mixed ????????????????
- */
- function getIdDef()
- {
- return $this->id_def;
- }
- // }}}
- // {{{ getId
- /**
- * ??????ID(primary key??)???
- *
- * @access public
- * @return mixed ??????ID
- */
- function getId()
- {
- return $this->id;
- }
- // }}}
- // {{{ get
- /**
- * ?????????????????(R)
- *
- * @access public
- * @param string $key ??????(????)
- * @return mixed ?????(?????)
- */
- function get($key)
- {
- if (isset($this->prop_def[$key]) == false) {
- trigger_error(sprintf("Unknown property [%s]", $key), E_USER_ERROR);
- return null;
- }
- if (isset($this->prop[$key])) {
- return $this->prop[$key];
- }
- return null;
- }
- // }}}
- // {{{ getName
- /**
- * ????????????????????
- * ?????????????????? (???????
- * ?????????????
- *
- * ????????????????
- *
- * @access public
- * @param string $key ?????(???)?
- * @return string ?????(???)????
- */
- function getName($key)
- {
- return $this->get($key);
- }
- // }}}
- /**
- * ??????????????(??)??????
- * ?????????????????? (???????
- * ?????????????
- *
- * @access public
- * @param string $key ?????(???)?
- * @return string ?????(???)????(??)
- */
- function getLongName($key)
- {
- return $this->get($key);
- }
- // }}}
- // {{{ getNameObject
- /**
- * ??????????????????????
- * ???? getName ???????????????????
- *
- * @access public
- * @return array ?????????????????
- */
- function getNameObject()
- {
- $object = array();
- foreach ($this->prop_def as $key => $elt) {
- $object[$elt['form_name']] = $this->getName($key);
- }
- return $object;
- }
- // }}}
- // {{{ set
- /**
- * ???????????(?????????)???????
- *
- * @access public
- * @param string $key ?????(???)?
- * @param string $value ??????
- */
- function set($key, $value)
- {
- if (isset($this->prop_def[$key]) == false) {
- trigger_error(sprintf("Unknown property [%s]", $key), E_USER_ERROR);
- return null;
- }
- $this->prop[$key] = $value;
- }
- // }}}
- // {{{ dump
- /**
- * ???????????????????????(???CSV????????)
- *
- * @access public
- * @param string $type ?????("csv"...)
- * @return string ?????(???????null)
- */
- function dump($type = "csv")
- {
- $method = "_dump_$type";
- if (method_exists($this, $method) == false) {
- return Ethna::raiseError("Undefined Method [%s]", E_APP_NOMETHOD, $method);
- }
- return $this->$method();
- }
- // }}}
- // {{{ importForm
- /**
- * ??????????????????????????
- *
- * @access public
- * @param int $option ??????????
- * OBJECT_IMPORT_IGNORE_NULL: ?????????????????????
- * OBJECT_IMPORT_CONVERT_NULL: ????????????????????????
- */
- function importForm($option = null)
- {
- foreach ($this->getDef() as $k => $def) {
- $value = $this->af->get($def['form_name']);
- if (is_null($value)) {
- // ??????????????????????
- if ($option == OBJECT_IMPORT_IGNORE_NULL) {
- // null?????
- continue;
- } else if ($option == OBJECT_IMPORT_CONVERT_NULL) {
- // ???????
- $value = '';
- }
- }
- $this->set($k, $value);
- }
- }
- // }}}
- // {{{ exportForm
- /**
- * ??????????????????????????
- *
- * @access public
- */
- function exportForm()
- {
- foreach ($this->getDef() as $k => $def) {
- $this->af->set($def['form_name'], $this->get($k));
- }
- }
- // }}}
- // {{{ add
- /**
- * ???????????(INSERT)
- *
- * @access public
- * @return mixed 0:???? Ethna_Error:???
- * @todo remove dependency on PEAR::DB
- */
- function add()
- {
- // primary key ??? sequence ????
- // next id???: (pgsql?????)
- // ??????????id???
- foreach (to_array($this->id_def) as $id_def) {
- if (isset($this->prop_def[$id_def]['seq'])
- && $this->prop_def[$id_def]['seq']) {
- // NOTE: ??app object????insert????????
- $next_id = $this->my_db_rw->getNextId(
- $this->prop_def[$id_def]['table'], $id_def);
- if ($next_id !== null && $next_id >= 0) {
- $this->prop[$id_def] = $next_id;
- }
- break;
- }
- }
- // INSERT ????????
- $sql = $this->_getSQL_Add();
- for ($i = 0; $i < 4; $i++) {
- $r = $this->my_db_rw->query($sql);
- // ?????? -> ???????????????
- if (Ethna::isError($r)) {
- if ($r->getCode() == E_DB_DUPENT) {
- // ??????????
- $duplicate_key_list = $this->_getDuplicateKeyList();
- if (Ethna::isError($duplicate_key_list)) {
- return $duplicate_key_list;
- }
- if (is_array($duplicate_key_list)
- && count($duplicate_key_list) > 0) {
- foreach ($duplicate_key_list as $k) {
- return Ethna::raiseNotice('Duplicate Key Error [%s]',
- E_APP_DUPENT, $k);
- }
- }
- } else {
- return $r;
- }
- } else {
- break;
- }
- }
- if ($i == 4) {
- // cannot be reached
- return Ethna::raiseError('Cannot detect Duplicate key Error', E_GENERAL);
- }
- // last insert id???: (mysql, sqlite??)
- // primary key ? 'seq' ??????(???)?????????
- $insert_id = $this->my_db_rw->getInsertId();
- if ($insert_id !== null && $insert_id >= 0) {
- foreach (to_array($this->id_def) as $id_def) {
- if (isset($this->prop_def[$id_def]['seq'])
- && $this->prop_def[$id_def]['seq']) {
- $this->prop[$id_def] = $insert_id;
- break;
- }
- }
- }
- // ID(Primary Key)?????
- if (is_array($this->id_def)) {
- $this->id = array();
- foreach ($this->id_def as $k) {
- $this->id[] = $this->prop[$k];
- }
- } else if (isset($this->prop[$this->id_def])) {
- $this->id = $this->prop[$this->id_def];
- } else {
- trigger_error("primary key is missing", E_USER_ERROR);
- }
- // ??????/???????
- $this->prop_backup = $this->prop;
- $this->_clearPropCache();
- return 0;
- }
- // }}}
- // {{{ update
- /**
- * ???????????(UPDATE)
- *
- * @access public
- * @return mixed 0:???? Ethna_Error:???
- * @todo remove dependency on PEAR::DB
- */
- function update()
- {
- $sql = $this->_getSQL_Update();
- // ?????? -> ???????????????(4?)
- for ($i = 0; $i < 4; $i++) { // magic number
- $r = $this->my_db_rw->query($sql);
- if (Ethna::isError($r)) {
- if ($r->getCode() == E_DB_DUPENT) {
- // ??????????
- $duplicate_key_list = $this->_getDuplicateKeyList();
- if (Ethna::isError($duplicate_key_list)) {
- return $duplicate_key_list;
- }
- if (is_array($duplicate_key_list)
- && count($duplicate_key_list) > 0) {
- foreach ($duplicate_key_list as $k) {
- return Ethna::raiseNotice('Duplicate Key Error [%s]',
- E_APP_DUPENT, $k);
- }
- }
- } else {
- return $r;
- }
- } else {
- break;
- }
- }
- if ($i == 4) {
- // cannot be reached
- return Ethna::raiseError('Cannot detect Duplicate key Error', E_GENERAL);
- }
- $affected_rows = $this->my_db_rw->affectedRows();
- if ($affected_rows <= 0) {
- $this->backend->log(LOG_DEBUG, "update query with 0 updated rows");
- }
- // ??????/???????
- $this->prop_backup = $this->prop;
- $this->_clearPropCache();
- return 0;
- }
- // }}}
- // {{{ replace
- /**
- * ???????????
- *
- * MySQL?REPLACE???????????(add()????????????
- * update()???)
- *
- * @access public
- * @return mixed 0:???? >0:??????ID(???) Ethna_Error:???
- * @todo remove dependency on PEAR::DB
- */
- function replace()
- {
- $sql = $this->_getSQL_Select($this->getIdDef(), $this->getId());
- // ???????????????(4?)
- for ($i = 0; $i < 3; $i++) { // magic number
- $r = $this->my_db_rw->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- }
- $n = $r->numRows();
- if ($n > 0) {
- $r = $this->update();
- return $r;
- } else {
- $r = $this->add();
- if (Ethna::isError($r) == false) {
- return $r;
- } else if ($r->getCode() != E_APP_DUPENT) {
- return $r;
- }
- }
- }
-
- return $r;
- }
- // }}}
- // {{{ remove
- /**
- * ??????(????)?????
- *
- * @access public
- * @return mixed 0:???? Ethna_Error:???
- * @todo remove dependency on PEAR::DB
- */
- function remove()
- {
- $sql = $this->_getSQL_Remove();
- $r = $this->my_db_rw->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- }
- // ?????/??????/????????
- $this->id = $this->prop = $this->prop_backup = null;
- $this->_clearPropCache();
- return 0;
- }
- // }}}
- // {{{ searchId
- /**
- * ??????ID(??????????)?????
- *
- * @access public
- * @param array $filter WHERE????(???????????????????Ethna_AppSearchObject???)
- * @param array $order ?????????
- * (?????????????????? OBJECT_SORT_ASC, ???????OBJECT_SORT_DESC)
- * @param int $offset ???????????
- * @param int $count ???????
- * @return mixed array(0 => ????????????,
- * 1 => $offset, $count?????????????????ID??)
- * Ethna_Error:???
- * TODO: remove dependency on PEAR::DB
- */
- function searchId($filter = null, $order = null, $offset = null, $count = null)
- {
- // ????????????
- if (is_null($offset) == false || is_null($count) == false) {
- $sql = $this->_getSQL_SearchLength($filter);
- $r = $this->my_db_ro->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- }
- $row = $this->my_db_ro->fetchRow($r, DB_FETCHMODE_ASSOC);
- $length = $row['id_count'];
- } else {
- $length = null;
- }
- $id_list = array();
- $sql = $this->_getSQL_SearchId($filter, $order, $offset, $count);
- $r = $this->my_db_ro->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- }
- $n = $r->numRows();
- for ($i = 0; $i < $n; $i++) {
- $row = $this->my_db_ro->fetchRow($r, DB_FETCHMODE_ASSOC);
- // ????????1?????????????
- if (is_array($this->id_def) == false) {
- $row = $row[$this->id_def];
- }
- $id_list[] = $row;
- }
- if (is_null($length)) {
- $length = count($id_list);
- }
- return array($length, $id_list);
- }
- // }}}
- // {{{ searchProp
- /**
- * ???????????(????)?????
- *
- * @access public
- * @param array $keys ?????????(????)
- * @param array $filter WHERE????(???????????????????Ethna_AppSearchObject???)
- * @param array $order ?????????
- * (?????????????????? OBJECT_SORT_ASC, ???????OBJECT_SORT_DESC)
- * @param int $offset ???????????
- * @param int $count ???????
- * @return mixed array(0 => ????????????,
- * 1 => $offset, $count????????????????????????)
- * Ethna_Error:???
- * TODO: remove dependency on PEAR::DB
- */
- function searchProp($keys = null, $filter = null, $order = null,
- $offset = null, $count = null)
- {
- // ????????????
- if (is_null($offset) == false || is_null($count) == false) {
- $sql = $this->_getSQL_SearchLength($filter);
- $r = $this->my_db_ro->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- }
- $row = $this->my_db_ro->fetchRow($r, DB_FETCHMODE_ASSOC);
- $length = $row['id_count'];
- } else {
- $length = null;
- }
- $prop_list = array();
- $sql = $this->_getSQL_SearchProp($keys, $filter, $order, $offset, $count);
- $r = $this->my_db_ro->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- }
- $n = $r->numRows();
- for ($i = 0; $i < $n; $i++) {
- $row = $this->my_db_ro->fetchRow($r, DB_FETCHMODE_ASSOC);
- $prop_list[] = $row;
- }
- if (is_null($length)) {
- $length = count($prop_list);
- }
- return array($length, $prop_list);
- }
- // }}}
- // {{{ _setDefault
- /**
- * ??????????????????????????????
- *
- * ???????????????????????????????????
- * ????????????????????????
- *
- * @access protected
- * @param mixed $key_type ?????
- * @param mixed $key ????
- * @return int 0:????
- */
- function _setDefault($key_type, $key)
- {
- return 0;
- }
- // }}}
- // {{{ _setPropByDB
- /**
- * ????????????DB??????
- *
- * @access private
- * @param mixed $key_type ?????
- * @param mixed $key ????
- * TODO: depend on PEAR::DB
- */
- function _setPropByDB($key_type, $key)
- {
- global $_ETHNA_APP_OBJECT_CACHE;
- $key_type = to_array($key_type);
- $key = to_array($key);
- if (count($key_type) != count($key)) {
- trigger_error(sprintf("Unmatched key_type & key length [%d-%d]",
- count($key_type), count($key)), E_USER_ERROR);
- return;
- }
- foreach ($key_type as $elt) {
- if (isset($this->prop_def[$elt]) == false) {
- trigger_error("Invalid key_type [$elt]", E_USER_ERROR);
- return;
- }
- }
- // ?????????
- $class_name = strtolower(get_class($this));
- if (is_array($_ETHNA_APP_OBJECT_CACHE) == false
- || array_key_exists($class_name, $_ETHNA_APP_OBJECT_CACHE) == false) {
- $_ETHNA_APP_OBJECT_CACHE[$class_name] = array();
- }
- $cache_key = serialize(array($key_type, $key));
- if (array_key_exists($cache_key, $_ETHNA_APP_OBJECT_CACHE[$class_name])) {
- $this->prop = $_ETHNA_APP_OBJECT_CACHE[$class_name][$cache_key];
- return;
- }
- // SQL???
- $sql = $this->_getSQL_Select($key_type, $key);
- // ???????
- $r = $this->my_db_ro->query($sql);
- if (Ethna::isError($r)) {
- return;
- }
- $n = $r->numRows();
- if ($n == 0) {
- // try default
- if ($this->_setDefault($key_type, $key) == false) {
- // nop
- }
- return;
- } else if ($n > 1) {
- trigger_error("Invalid key (multiple rows found) [$key]", E_USER_ERROR);
- return;
- }
- $this->prop = $this->my_db_ro->fetchRow($r, DB_FETCHMODE_ASSOC);
- // ???????????
- $_ETHNA_APP_OBJECT_CACHE[$class_name][$cache_key] = $this->prop;
- }
- // }}}
- // {{{ _setPropByValue
- /**
- * ???????????????????????
- *
- * @access private
- * @param array $prop ???????
- */
- function _setPropByValue($prop)
- {
- $def = $this->getDef();
- foreach ($def as $key => $value) {
- if ($value['primary'] && isset($prop[$key]) == false) {
- // ????????????
- trigger_error("primary key is not identical", E_USER_ERROR);
- }
- $this->prop[$key] = $prop[$key];
- }
- }
- // }}}
- // {{{ _getPrimaryTable
- /**
- * ?????????????????????
- *
- * @access private
- * @return string ?????????????????
- */
- function _getPrimaryTable()
- {
- $tables = array_keys($this->table_def);
- $table = $tables[0];
-
- return $table;
- }
- // }}}
- // {{{ _getDuplicateKeyList
- /**
- * ?????????
- *
- * @access private
- * @return mixed 0:???? Ethna_Error:??? array:?????????????
- * TODO: depend on PEAR::DB
- */
- function _getDuplicateKeyList()
- {
- $duplicate_key_list = array();
- // ?????????????????NULL?????????????
- $check_pkey = true;
- foreach (to_array($this->id_def) as $k) {
- if (isset($this->prop[$k]) == false || is_null($this->prop[$k])) {
- $check_pkey = false;
- break;
- }
- }
- // ????????multi columns??????????
- if ($check_pkey) {
- $sql = $this->_getSQL_Duplicate($this->id_def);
- $r = $this->my_db_rw->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- } else if ($r->numRows() > 0) {
- // we can overwrite $key_list here
- $duplicate_key_list = to_array($this->id_def);
- }
- }
- // ??????
- foreach ($this->prop_def as $k => $v) {
- if ($v['primary'] == true || $v['key'] == false) {
- continue;
- }
- $sql = $this->_getSQL_Duplicate($k);
- $r = $this->my_db_rw->query($sql);
- if (Ethna::isError($r)) {
- return $r;
- } else if ($r->NumRows() > 0) {
- $duplicate_key_list[] = $k;
- }
- }
- if (count($duplicate_key_list) > 0) {
- return $duplicate_key_list;
- } else {
- return 0;
- }
- }
- // }}}
- // {{{ _getSQL_Select
- /**
- * ????????????????SQL??????
- *
- * @access private
- * @param array $key_type ????????????(???)???
- * @param array $key $key_type?????????
- * @return string SELECT?
- */
- function _getSQL_Select($key_type, $key)
- {
- $key_type = to_array($key_type);
- if (is_null($key)) {
- // add()?
- $key = array();
- for ($i = 0; $i < count($key_type); $i++) {
- $key[$i] = null;
- }
- } else {
- $key = to_array($key);
- }
- // SQL?????
- Ethna_AppSQL::escapeSQL($key, $this->my_db_type);
- $tables = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->table_def)));
- $columns = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->prop_def)));
- // ????
- $condition = null;
- for ($i = 0; $i < count($key_type); $i++) {
- if (is_null($condition)) {
- $condition = "WHERE ";
- } else {
- $condition .= " AND ";
- }
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_ro->quoteIdentifier($key_type[$i]), $key[$i]);
- }
- $sql = "SELECT $columns FROM $tables $condition";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_Add
- /**
- * ???????????SQL??????
- *
- * @access private
- * @return string ??????????????INSERT?
- */
- function _getSQL_Add()
- {
- $tables = implode(',',
- $this->my_db_rw->quoteIdentifier(array_keys($this->table_def)));
- $key_list = array();
- $set_list = array();
- $prop_arg_list = $this->prop;
- Ethna_AppSQL::escapeSQL($prop_arg_list, $this->my_db_type);
- foreach ($this->prop_def as $k => $v) {
- if (isset($prop_arg_list[$k]) == false) {
- continue;
- }
- $key_list[] = $this->my_db_rw->quoteIdentifier($k);
- $set_list[] = $prop_arg_list[$k];
- }
- $key_list = implode(', ', $key_list);
- $set_list = implode(', ', $set_list);
- $sql = "INSERT INTO $tables ($key_list) VALUES ($set_list)";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_Update
- /**
- * ????????????????SQL??????
- *
- * @access private
- * @return ???????????????????UPDATE?
- */
- function _getSQL_Update()
- {
- $tables = implode(',',
- $this->my_db_rw->quoteIdentifier(array_keys($this->table_def)));
- // SET???
- $set_list = "";
- $prop_arg_list = $this->prop;
- Ethna_AppSQL::escapeSQL($prop_arg_list, $this->my_db_type);
- foreach ($this->prop_def as $k => $v) {
- if ($set_list != "") {
- $set_list .= ",";
- }
- $set_list .= sprintf("%s=%s",
- $this->my_db_rw->quoteIdentifier($k),
- $prop_arg_list[$k]);
- }
- // ????(primary key)
- $condition = null;
- foreach (to_array($this->id_def) as $k) {
- if (is_null($condition)) {
- $condition = "WHERE ";
- } else {
- $condition .= " AND ";
- }
- $v = $this->prop_backup[$k]; // equals to $this->id
- Ethna_AppSQL::escapeSQL($v, $this->my_db_type);
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_rw->quoteIdentifier($k), $v);
- }
- $sql = "UPDATE $tables SET $set_list $condition";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_Remove
- /**
- * ???????????SQL??????
- *
- * @access private
- * @return string ??????????????DELETE?
- */
- function _getSQL_Remove()
- {
- $tables = implode(',',
- $this->my_db_rw->quoteIdentifier(array_keys($this->table_def)));
- // ????(primary key)
- $condition = null;
- foreach (to_array($this->id_def) as $k) {
- if (is_null($condition)) {
- $condition = "WHERE ";
- } else {
- $condition .= " AND ";
- }
- $v = $this->prop_backup[$k]; // equals to $this->id
- Ethna_AppSQL::escapeSQL($v, $this->my_db_type);
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_rw->quoteIdentifier($k), $v);
- }
- if (is_null($condition)) {
- trigger_error("DELETE with no conditon", E_USER_ERROR);
- return null;
- }
- $sql = "DELETE FROM $tables $condition";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_Duplicate
- /**
- * ???????????????????????SQL??????
- *
- * @access private
- * @param mixed $key ?????????????????
- * @return string ??????????????SELECT?
- */
- function _getSQL_Duplicate($key)
- {
- $tables = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->table_def)));
- $columns = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->prop_def)));
- $condition = null;
- // ????(?????????????????????????)
- if (is_null($this->id) == false) {
- $primary_value = to_array($this->getId());
- $n = 0;
- foreach (to_array($this->id_def) as $k) {
- if (is_null($condition)) {
- $condition = "WHERE ";
- } else {
- $condition .= " AND ";
- }
- $value = $primary_value[$n];
- Ethna_AppSQL::escapeSQL($value, $this->my_db_type);
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_ro->quoteIdentifier($k), $value, OBJECT_CONDITION_NE);
- $n++;
- }
- }
- foreach (to_array($key) as $k) {
- if (is_null($condition)) {
- $condition = "WHERE ";
- } else {
- $condition .= " AND ";
- }
- $v = $this->prop[$k];
- Ethna_AppSQL::escapeSQL($v, $this->my_db_type);
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_ro->quoteIdentifier($k), $v);
- }
- $sql = "SELECT $columns FROM $tables $condition";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_SearchLength
- /**
- * ??????????(offset, count??)?????SQL??????
- *
- * @access private
- * @param array $filter WHERE????(???????????????????Ethna_AppSearchObject???)
- * @return string ????????????SELECT?
- * @todo my_db_type??????
- */
- function _getSQL_SearchLength($filter)
- {
- // ?????????????????
- $tables = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->table_def)));
- // ??????????????????????
- // ??????????????????
- // ????? _SQLPlugin_SearchTable ????
- if ($this->_isAdditionalField($filter)) {
- $tables .= " " . $this->_SQLPlugin_SearchTable();
- }
- $id_def = to_array($this->id_def);
- // ?????.?????????
- // ?????????????????
- $column_id = $this->my_db_ro->quoteIdentifier($this->_getPrimaryTable())
- . "." . $this->my_db_ro->quoteIdentifier($id_def[0]);
- $id_count = $this->my_db_ro->quoteIdentifier('id_count');
- $condition = $this->_getSQL_SearchCondition($filter);
- if ($this->my_db_type === 'sqlite') {
- $sql = "SELECT COUNT(*) AS $id_count FROM "
- . " (SELECT DISTINCT $column_id FROM $tables $condition)";
- } else {
- $sql = "SELECT COUNT(DISTINCT $column_id) AS $id_count "
- . "FROM $tables $condition";
- }
- return $sql;
- }
- // }}}
- // {{{ _getSQL_SearchId
- /**
- * ??????ID(????????)?????SQL??????
- *
- * @access private
- * @param array $filter WHERE????(???????????????????Ethna_AppSearchObject???)
- * @param array $order ?????????
- * (?????????????????? OBJECT_SORT_ASC, ???????OBJECT_SORT_DESC)
- * @param int $offset ???????????
- * @param int $count ???????
- * @return string ???????????SELECT?
- */
- function _getSQL_SearchId($filter, $order, $offset, $count)
- {
- // ????
- $tables = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->table_def)));
- if ($this->_isAdditionalField($filter)
- || $this->_isAdditionalField($order)) {
- $tables .= " " . $this->_SQLPlugin_SearchTable();
- }
- $column_id = "";
- foreach (to_array($this->id_def) as $id) {
- if ($column_id != "") {
- $column_id .= ",";
- }
- $column_id .= $this->my_db_ro->quoteIdentifier($this->_getPrimaryTable())
- . "." . $this->my_db_ro->quoteIdentifier($id);
- }
- $condition = $this->_getSQL_SearchCondition($filter);
- $sort = "";
- if (is_array($order)) {
- foreach ($order as $k => $v) {
- if ($sort == "") {
- $sort = "ORDER BY ";
- } else {
- $sort .= ", ";
- }
- $sort .= sprintf("%s %s", $this->my_db_ro->quoteIdentifier($k),
- $v == OBJECT_SORT_ASC ? "ASC" : "DESC");
- }
- }
- $limit = "";
- if (is_null($count) == false) {
- $limit = sprintf("LIMIT %d", $count);
- if (is_null($offset) == false) {
- $limit .= sprintf(" OFFSET %d", $offset);
- }
- }
- $sql = "SELECT DISTINCT $column_id FROM $tables $condition $sort $limit";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_SearchProp
- /**
- * ????????????????SQL??????
- *
- * @access private
- * @param array $keys ???????(????)??
- * @param array $filter WHERE????(???????????????????Ethna_AppSearchObject???)
- * @param array $order ?????????
- * (?????????????????? OBJECT_SORT_ASC, ???????OBJECT_SORT_DESC)
- * @param int $offset ???????????
- * @param int $count ???????
- * @return string ???????????SELECT?
- */
- function _getSQL_SearchProp($keys, $filter, $order, $offset, $count)
- {
- // ????
- $tables = implode(',',
- $this->my_db_ro->quoteIdentifier(array_keys($this->table_def)));
- if ($this->_isAdditionalField($filter)
- || $this->_isAdditionalField($order)) {
- $tables .= " " . $this->_SQLPlugin_SearchTable();
- }
- $p_table = $this->_getPrimaryTable();
- // ??????????
- // ??????????????????????
- // ????????? _SQLPlugin_SearchPropDef ????
- //
- // ?????????????????????????
- // ???(??. ?????)
- if ($this->_isAdditionalField($filter)
- || $this->_isAdditionalField($order)) {
- $search_prop_def = $this->_SQLPlugin_SearchPropDef();
- } else {
- $search_prop_def = array();
- }
- $def = array_merge($this->getDef(), $search_prop_def);
- // ???
- $column = "";
- $keys = $keys === null ? array_keys($def) : to_array($keys);
- foreach ($keys as $key) {
- if ($column != "") {
- $column .= ", ";
- }
- $t = isset($def[$key]['table']) ? $def[$key]['table'] : $p_table;
- // ?????.????
- $column .= sprintf("%s.%s",
- $this->my_db_ro->quoteIdentifier($t),
- $this->my_db_ro->quoteIdentifier($key));
- }
- // WHERE ???
- $condition = $this->_getSQL_SearchCondition($filter);
- // ORDER BY
- $sort = "";
- if (is_array($order)) {
- foreach ($order as $k => $v) {
- if ($sort == "") {
- $sort = "ORDER BY ";
- } else {
- $sort .= ", ";
- }
- $sort .= sprintf("%s %s",
- $this->my_db_ro->quoteIdentifier($k),
- $v == OBJECT_SORT_ASC ? "ASC" : "DESC");
- }
- }
- // LIMIT, OFFSET
- $limit = "";
- if (is_null($count) == false) {
- $limit = sprintf("LIMIT %d", $count);
- if (is_null($offset) == false) {
- $limit .= sprintf(" OFFSET %d", $offset);
- }
- }
- $sql = "SELECT $column FROM $tables $condition $sort $limit";
- return $sql;
- }
- // }}}
- // {{{ _getSQL_SearchCondition
- /**
- * ????????SQL?????????
- *
- * @access private
- * @param array $filter WHERE????(???????????????????Ethna_AppSearchObject???)
- * @return string ????????????(?????null)
- */
- function _getSQL_SearchCondition($filter)
- {
- if (is_array($filter) == false) {
- return "";
- }
- $p_table = $this->_getPrimaryTable();
- // ??????????
- // ??????????????????????
- // ????????? _SQLPlugin_SearchPropDef ????
- //
- // ?????????????????????????
- // ???(??. ?????)
- if ($this->_isAdditionalField($filter)) {
- $search_prop_def = $this->_SQLPlugin_SearchPropDef();
- } else {
- $search_prop_def = array();
- }
- $prop_def = array_merge($this->prop_def, $search_prop_def);
- $condition = null;
- foreach ($filter as $k => $v) {
- if (isset($prop_def[$k]) == false) {
- trigger_error(sprintf("Unknown property [%s]", $k), E_USER_ERROR);
- return null;
- }
- if (is_null($condition)) {
- $condition = "WHERE ";
- } else {
- $condition .= " AND ";
- }
- $t = isset($prop_def[$k]['table']) ? $prop_def[$k]['table'] : $p_table;
- // ?????????????Ethna_AppSearchObject
- // ???????? ??????? LIKE, ?????
- // ? = ????????????????
- if (is_object($v)) {
- // Ethna_AppSearchObject??????????
- $condition .= $v->toString(
- $this->my_db_ro->quoteIdentifier($t)
- .'.'. $this->my_db_ro->quoteIdentifier($k));
- } else if (is_array($v) && count($v) > 0 && is_object($v[0])) {
- // Ethna_AppSearchObject?????????????
- $n = 0;
- foreach ($v as $so) {
- if ($n > 0) {
- $condition .= " AND ";
- }
- $condition .= $so->toString(
- $this->my_db_ro->quoteIdentifier($t)
- .'.'. $this->my_db_ro->quoteIdentifier($k));
- $n++;
- }
- } else if ($prop_def[$k]['type'] == VAR_TYPE_STRING) {
- // ???(???)
- Ethna_AppSQL::escapeSQL($v, $this->my_db_type);
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_ro->quoteIdentifier($t)
- .'.'. $this->my_db_ro->quoteIdentifier($k),
- $v, OBJECT_CONDITION_LIKE);
- } else {
- // ???(??)
- Ethna_AppSQL::escapeSQL($v, $this->my_db_type);
- $condition .= Ethna_AppSQL::getCondition(
- $this->my_db_ro->quoteIdentifier($t)
- .'.'. $this->my_db_ro->quoteIdentifier($k),
- $v, OBJECT_CONDITION_EQ);
- }
- }
- return $condition;
- }
- // }}}
- // {{{ _SQLPlugin_SearchTable
- /**
- * ????????SQL?????(??????)
- *
- * sample:
- * <code>
- * return " LEFT JOIN bar_tbl ON foo_tbl.user_id=bar_tbl.user_id";
- * </code>
- *
- * @access protected
- * @return string ????JOIN?SQL?
- */
- function _SQLPlugin_SearchTable()
- {
- return "";
- }
- // }}}
- // {{{ _SQLPlugin_SearchPropDef
- /**
- * ????????SQL?????(??????)
- *
- * sample:
- * <code>
- * $search_prop_def = array(
- * 'group_id' => array(
- * 'primary' => true, 'key' => true, 'type' => VAR_TYPE_INT,
- * 'form_name' => 'group_id', 'table' => 'group_user_tbl',
- * ),
- * );
- * return $search_prop_def;
- * </code>
- *
- * @access protected
- * @return array ??????
- */
- function _SQLPlugin_SearchPropDef()
- {
- return array();
- }
- // }}}
- // {{{ _dump_csv
- /**
- * ????????????CSV????????
- *
- * @access protected
- * @return string ?????
- */
- function _dump_csv()
- {
- $dump = "";
- $n = 0;
- foreach ($this->getDef() as $k => $def) {
- if ($n > 0) {
- $dump .= ",";
- }
- $dump .= Ethna_Util::escapeCSV($this->getName($k));
- $n++;
- }
- return $dump;
- }
- // }}}
- // {{{ _isAdditionalField
- /**
- * (????|?????)????????????????
- * ????????????????????
- *
- * @access private
- * @param array $field (????|?????)??
- * @return bool true:???? false:?????
- */
- function _isAdditionalField($field)
- {
- if (is_array($field) == false) {
- return false;
- }
- $def = $this->getDef();
- foreach ($field as $key => $value) {
- if (array_key_exists($key, $def) == false) {
- return true;
- }
- if (is_object($value)) {
- // Ethna_AppSearchObject
- if ($value->isTarget($key)) {
- return true;
- }
- }
- }
- return false;
- }
- // }}}
- // {{{ _clearPropCache
- /**
- * ?????????????
- *
- * @access private
- */
- function _clearPropCache()
- {
- $class_name = strtolower(get_class($this));
- foreach (array('_ETHNA_APP_OBJECT_CACHE',
- '_ETHNA_APP_MANAGER_OL_CACHE',
- '_ETHNA_APP_MANAGER_OPL_CACHE',
- '_ETHNA_APP_MANAGER_OP_CACHE') as $key) {
- if (array_key_exists($key, $GLOBALS)
- && array_key_exists($class_name, $GLOBALS[$key])) {
- unset($GLOBALS[$key][$class_name]);
- }
- }
- }
- // }}}
- // {{{ _getDBList
- /**
- * DB??????(read only/read-write)?????
- *
- * @access protected
- * @return array array('ro' => {read only db object}, 'rw' => {read-write db object})
- */
- function _getDBList()
- {
- $r = array('ro' => null, 'rw' => null);
- $db_list = $this->backend->getDBList();
- if (Ethna::isError($db_list)) {
- return $r;
- }
- foreach ($db_list as $elt) {
- if ($this->db_prefix) {
- // ???????????????DB?????
- // (???????DB????????)
- if (strncmp($this->db_prefix,
- $elt['key'],
- strlen($this->db_prefix)) != 0) {
- continue;
- }
- }
- $varname = $elt['varname'];
- // for B.C.
- $this->$varname = $elt['db'];
- if ($elt['type'] == DB_TYPE_RW) {
- $r['rw'] = $elt['db'];
- } else if ($elt['type'] == DB_TYPE_RO) {
- $r['ro'] = $elt['db'];
- }
- }
- if ($r['ro'] == null && $r['rw'] != null) {
- $r['ro'] = $r['rw'];
- }
- return $r;
- }
- // }}}
- // {{{ _getTableDef
- /**
- * ???????????
- *
- * (??????????????????????
- * ?????????????????)
- *
- * @access protected
- * @return array ??????
- */
- function _getTableDef()
- {
- $class_name = get_class($this);
- if (preg_match('/(\w+)_(.*)/', $class_name, $match) == 0) {
- return null;
- }
- $table = $match[2];
- // PHP 4?????????...??PHP 5??
- $table = preg_replace('/^([A-Z])/e', "strtolower('\$1')", $table);
- $table = preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $table);
- // JOIN ??????????????????????
- // ??????? primary ? true???
- return array($table => array('primary' => true));
- }
- // }}}
- // {{{ _getPropDef
- /**
- * ????????????????????????????
- * ??????????
- *
- * @access protected
- * @return array ???????
- */
- function _getPropDef()
- {
- if (is_null($this->table_def)) {
- return null;
- }
- foreach ($this->table_def as $table_name => $table_attr) {
- // use 1st one
- break;
- }
- $cache_manager = Ethna_CacheManager::getInstance('localfile');
- $cache_manager->setNamespace('ethna_app_object');
- $cache_key = md5($this->my_db_ro->getDSN() . '-' . $table_name);
- if ($cache_manager->isCached($cache_key, $this->prop_def_cache_lifetime)) {
- $prop_def = $cache_manager->get($cache_key,
- $this->prop_def_cache_lifetime);
- if (Ethna::isError($prop_def) == false) {
- return $prop_def;
- }
- }
- $r = $this->my_db_ro->getMetaData($table_name);
- if(Ethna::isError($r)){
- return null;
- }
- $prop_def = array();
- foreach ($r as $i => $field_def) {
- $primary = in_array('primary_key', $field_def['flags']);
- $seq = in_array('sequence', $field_def['flags']);
- $required = in_array('not_null', $field_def['flags']);
- $key = in_array('primary_key', $field_def['flags'])
- || in_array('multiple_key', $field_def['flags'])
- || in_array('unique_key', $field_def['flags']);
- switch ($field_def['type']) {
- case 'int':
- $type = VAR_TYPE_INT;
- break;
- case 'boolean':
- $type = VAR_TYPE_BOOLEAN;
- break;
- case 'datetime':
- $type = VAR_TYPE_DATETIME;
- break;
- default:
- $type = VAR_TYPE_STRING;
- break;
- }
- $prop_def[$field_def['name']] = array(
- 'primary' => $primary,
- 'seq' => $seq,
- 'key' => $key,
- 'type' => $type,
- 'required' => $required,
- 'length' => $field_def['len'],
- 'form_name' => $this->_fieldNameToFormName($field_def),
- 'table' => $table_name,
- );
- }
-
- $cache_manager->set($cache_key, $prop_def);
- return $prop_def;
- }
- // }}}
- // {{{ _fieldNameToFormName
- /**
- * ???????????????????????????
- *
- * @access protected
- */
- function _fieldNameToFormName($field_def)
- {
- return $field_def['name'];
- }
- // }}}
- }
- // }}}