Example #1
0
 /**
  * build the update() method for the final class
  * @return string the source of the method
  */
 protected function buildUpdateMethod($pkFields)
 {
     $src = array();
     $src[] = 'public function update ($record){';
     list($fields, $values) = $this->_prepareValues($this->_getPropertiesBy('PrimaryFieldsExcludePk'), 'updatePattern', 'record->');
     if (count($fields)) {
         if ($this->_dataParser->hasEvent('updatebefore') || $this->_dataParser->hasEvent('update')) {
             $src[] = '   jEvent::notify("daoUpdateBefore", array(\'dao\'=>$this->_daoSelector, \'record\'=>$record));';
         }
         $src[] = '   $query = \'UPDATE ' . $this->tableRealNameEsc . ' SET ';
         $sqlSet = '';
         foreach ($fields as $k => $fname) {
             $sqlSet .= ', ' . $fname . '= ' . $values[$k];
         }
         $src[] = substr($sqlSet, 1);
         $sqlCondition = $this->buildSimpleConditions($pkFields, 'record->', false);
         if ($sqlCondition != '') {
             $src[] = ' where ' . $sqlCondition;
         }
         $src[] = "';";
         $src[] = '   $result = $this->_conn->exec ($query);';
         // we generate a SELECT query to update field on the record object, which are autoincrement or calculated
         $fields = $this->_getPropertiesBy('FieldToUpdateOnUpdate');
         if (count($fields)) {
             $result = array();
             foreach ($fields as $id => $prop) {
                 $result[] = $this->buildSelectPattern($prop->selectPattern, '', $prop->fieldName, $prop->name);
             }
             $sql = 'SELECT ' . implode(', ', $result) . ' FROM ' . $this->tableRealNameEsc . ' WHERE ';
             $sql .= $this->buildSimpleConditions($pkFields, 'record->', false);
             $src[] = '  $query =\'' . $sql . '\';';
             $src[] = '  $rs  =  $this->_conn->query ($query, jDbConnection::FETCH_INTO, $record);';
             $src[] = '  $record =  $rs->fetch ();';
         }
         if ($this->_dataParser->hasEvent('updateafter') || $this->_dataParser->hasEvent('update')) {
             $src[] = '   jEvent::notify("daoUpdateAfter", array(\'dao\'=>$this->_daoSelector, \'record\'=>$record));';
         }
         $src[] = '   return $result;';
     } else {
         //the dao is mapped on a table which contains only primary key : update is impossible
         // so we will generate an error on update
         $src[] = "     throw new jException('jelix~dao.error.update.impossible',array('" . $this->_daoId . "','" . $this->_daoPath . "'));";
     }
     $src[] = ' }';
     //ends the update function
     return implode("\n", $src);
 }
 /**
  * build all classes
  */
 public final function buildClasses()
 {
     $src = array();
     $src[] = ' require_once ( JELIX_LIB_PATH .\'dao/jDaoRecordBase.class.php\');';
     $src[] = ' require_once ( JELIX_LIB_PATH .\'dao/jDaoFactoryBase.class.php\');';
     // prepare some values to generate properties and methods
     list($sqlFromClause, $sqlWhereClause) = $this->_getFromClause();
     $tables = $this->_dataParser->getTables();
     $sqlSelectClause = $this->_getSelectClause();
     $pkFields = $this->_getPropertiesBy('PkFields');
     $pTableRealName = $tables[$this->_dataParser->getPrimaryTable()]['realname'];
     $pTableRealNameEsc = $this->_encloseName('\'.$this->_conn->prefixTable(\'' . $pTableRealName . '\').\'');
     $pkai = $this->_getAutoIncrementPKField();
     $sqlPkCondition = $this->_buildSimpleConditions($pkFields);
     if ($sqlPkCondition != '') {
         $sqlPkCondition = ($sqlWhereClause != '' ? ' AND ' : ' WHERE ') . $sqlPkCondition;
     }
     //-----------------------
     // Build the record class
     //-----------------------
     $src[] = "\nclass " . $this->_DaoRecordClassName . ' extends jDaoRecordBase {';
     $properties = array();
     foreach ($this->_dataParser->getProperties() as $id => $field) {
         $properties[$id] = get_object_vars($field);
         if ($field->defaultValue !== null) {
             $src[] = ' public $' . $id . '=' . var_export($field->defaultValue, true) . ';';
         } else {
             $src[] = ' public $' . $id . ';';
         }
     }
     $src[] = '   public function getProperties() { return ' . $this->_DaoClassName . '::$_properties; }';
     $src[] = '   public function getPrimaryKeyNames() { return ' . $this->_DaoClassName . '::$_pkFields; }';
     $src[] = '}';
     //--------------------
     // Build the dao class
     //--------------------
     $src[] = "\nclass " . $this->_DaoClassName . ' extends jDaoFactoryBase {';
     $src[] = '   protected $_tables = ' . var_export($tables, true) . ';';
     $src[] = '   protected $_primaryTable = \'' . $this->_dataParser->getPrimaryTable() . '\';';
     $src[] = '   protected $_selectClause=\'' . $sqlSelectClause . '\';';
     $src[] = '   protected $_fromClause;';
     $src[] = '   protected $_whereClause=\'' . $sqlWhereClause . '\';';
     $src[] = '   protected $_DaoRecordClassName=\'' . $this->_DaoRecordClassName . '\';';
     $src[] = '   protected $_daoSelector = \'' . jDaoCompiler::$daoId . '\';';
     if ($this->trueValue != 1) {
         $src[] = '   protected $trueValue =' . var_export($this->trueValue, true) . ';';
         $src[] = '   protected $falseValue =' . var_export($this->falseValue, true) . ';';
     }
     if ($this->_dataParser->hasEvent('deletebefore') || $this->_dataParser->hasEvent('delete')) {
         $src[] = '   protected $_deleteBeforeEvent = true;';
     }
     if ($this->_dataParser->hasEvent('deleteafter') || $this->_dataParser->hasEvent('delete')) {
         $src[] = '   protected $_deleteAfterEvent = true;';
     }
     if ($this->_dataParser->hasEvent('deletebybefore') || $this->_dataParser->hasEvent('deleteby')) {
         $src[] = '   protected $_deleteByBeforeEvent = true;';
     }
     if ($this->_dataParser->hasEvent('deletebyafter') || $this->_dataParser->hasEvent('deleteby')) {
         $src[] = '   protected $_deleteByAfterEvent = true;';
     }
     $src[] = '   public static $_properties = ' . var_export($properties, true) . ';';
     $src[] = '   public static $_pkFields = array(' . $this->_writeFieldNamesWith($start = '\'', $end = '\'', $beetween = ',', $pkFields) . ');';
     $src[] = ' ';
     $src[] = 'public function __construct($conn){';
     $src[] = '   parent::__construct($conn);';
     $src[] = '   $this->_fromClause = \'' . $sqlFromClause . '\';';
     $src[] = '}';
     // cannot put this methods directly into jDaoBase because of a php bug on static methods/properties
     $src[] = '   public function getProperties() { return self::$_properties; }';
     $src[] = '   public function getPrimaryKeyNames() { return self::$_pkFields;}';
     $src[] = ' ';
     $src[] = ' protected function _getPkWhereClauseForSelect($pk){';
     $src[] = '   extract($pk);';
     $src[] = ' return \'' . $sqlPkCondition . '\';';
     $src[] = '}';
     $src[] = ' ';
     $src[] = 'protected function _getPkWhereClauseForNonSelect($pk){';
     $src[] = '   extract($pk);';
     $src[] = '   return \' where ' . $this->_buildSimpleConditions($pkFields, '', false) . '\';';
     $src[] = '}';
     //----- Insert method
     $src[] = 'public function insert ($record){';
     if ($pkai !== null) {
         // if there is an autoincrement field as primary key
         // if a value is given for the autoincrement field, then with do a full insert
         $src[] = ' if($record->' . $pkai->name . ' > 0 ){';
         $src[] = '    $query = \'INSERT INTO ' . $pTableRealNameEsc . ' (';
         $fields = $this->_getPropertiesBy('PrimaryTable');
         list($fields, $values) = $this->_prepareValues($fields, 'insertPattern', 'record->');
         $src[] = implode(',', $fields);
         $src[] = ') VALUES (';
         $src[] = implode(', ', $values);
         $src[] = ")';";
         $src[] = '}else{';
         $fields = $this->_getPropertiesBy($this->propertiesListForInsert);
     } else {
         $fields = $this->_getPropertiesBy('PrimaryTable');
     }
     // if there isn't a autoincrement as primary key, then we do a full insert.
     // if there isn't a value for the autoincrement field and if this is a mysql/sqlserver and pgsql,
     // we do an insert without given primary key. In other case, we do a full insert.
     $src[] = '    $query = \'INSERT INTO ' . $pTableRealNameEsc . ' (';
     list($fields, $values) = $this->_prepareValues($fields, 'insertPattern', 'record->');
     $src[] = implode(',', $fields);
     $src[] = ') VALUES (';
     $src[] = implode(', ', $values);
     $src[] = ")';";
     if ($pkai !== null) {
         $src[] = '}';
     }
     if ($this->_dataParser->hasEvent('insertbefore') || $this->_dataParser->hasEvent('insert')) {
         $src[] = '   jEvent::notify("daoInsertBefore", array(\'dao\'=>$this->_daoSelector, \'record\'=>$record));';
     }
     $src[] = '   $result = $this->_conn->exec ($query);';
     if ($pkai !== null) {
         $src[] = '   if(!$result)';
         $src[] = '       return false;';
         $src[] = '   if($record->' . $pkai->name . ' < 1 ) ';
         $src[] = $this->genUpdateAutoIncrementPK($pkai, $pTableRealName);
     }
     // we generate a SELECT query to update field on the record object, which are autoincrement or calculated
     $fields = $this->_getPropertiesBy('FieldToUpdate');
     if (count($fields)) {
         $result = array();
         foreach ($fields as $id => $prop) {
             $result[] = $this->genSelectPattern($prop->selectPattern, '', $prop->fieldName, $prop->name);
         }
         $sql = 'SELECT ' . implode(', ', $result) . ' FROM ' . $pTableRealNameEsc . ' WHERE ';
         $sql .= $this->_buildSimpleConditions($pkFields, 'record->', false);
         $src[] = '  $query =\'' . $sql . '\';';
         $src[] = '  $rs  =  $this->_conn->query ($query);';
         $src[] = '  $newrecord =  $rs->fetch ();';
         foreach ($fields as $id => $prop) {
             $src[] = '  $record->' . $prop->name . ' = $newrecord->' . $prop->name . ';';
         }
     }
     if ($this->_dataParser->hasEvent('insertafter') || $this->_dataParser->hasEvent('insert')) {
         $src[] = '   jEvent::notify("daoInsertAfter", array(\'dao\'=>$this->_daoSelector, \'record\'=>$record));';
     }
     $src[] = '    return $result;';
     $src[] = '}';
     //-----  update method
     $src[] = 'public function update ($record){';
     list($fields, $values) = $this->_prepareValues($this->_getPropertiesBy('PrimaryFieldsExcludePk'), 'updatePattern', 'record->');
     if (count($fields)) {
         $src[] = '   $query = \'UPDATE ' . $pTableRealNameEsc . ' SET ';
         $sqlSet = '';
         foreach ($fields as $k => $fname) {
             $sqlSet .= ', ' . $fname . '= ' . $values[$k];
         }
         $src[] = substr($sqlSet, 1);
         $sqlCondition = $this->_buildSimpleConditions($pkFields, 'record->', false);
         if ($sqlCondition != '') {
             $src[] = ' where ' . $sqlCondition;
         }
         $src[] = "';";
         if ($this->_dataParser->hasEvent('updatebefore') || $this->_dataParser->hasEvent('update')) {
             $src[] = '   jEvent::notify("daoUpdateBefore", array(\'dao\'=>$this->_daoSelector, \'record\'=>$record));';
         }
         $src[] = '   $result = $this->_conn->exec ($query);';
         // we generate a SELECT query to update field on the record object, which are autoincrement or calculated
         $fields = $this->_getPropertiesBy('FieldToUpdateOnUpdate');
         if (count($fields)) {
             $result = array();
             foreach ($fields as $id => $prop) {
                 $result[] = $this->genSelectPattern($prop->selectPattern, '', $prop->fieldName, $prop->name);
             }
             $sql = 'SELECT ' . implode(', ', $result) . ' FROM ' . $pTableRealNameEsc . ' WHERE ';
             $sql .= $this->_buildSimpleConditions($pkFields, 'record->', false);
             $src[] = '  $query =\'' . $sql . '\';';
             $src[] = '  $rs  =  $this->_conn->query ($query, jDbConnection::FETCH_INTO, $record);';
             $src[] = '  $record =  $rs->fetch ();';
         }
         if ($this->_dataParser->hasEvent('updateafter') || $this->_dataParser->hasEvent('update')) {
             $src[] = '   jEvent::notify("daoUpdateAfter", array(\'dao\'=>$this->_daoSelector, \'record\'=>$record));';
         }
         $src[] = '   return $result;';
         $src[] = ' }';
         //ends the update function
     } else {
         //the dao is mapped on a table which contains only primary key : update is impossible
         // so we will generate an error on update
         $src[] = "     throw new jException('jelix~dao.error.update.impossible',array('" . jDaoCompiler::$daoId . "','" . jDaoCompiler::$daoPath . "'));";
         $src[] = " }";
     }
     //----- other user methods
     $allField = $this->_getPropertiesBy('All');
     $primaryFields = $this->_getPropertiesBy('PrimaryTable');
     $ct = null;
     foreach ($this->_dataParser->getMethods() as $name => $method) {
         $defval = $method->getParametersDefaultValues();
         if (count($defval)) {
             $mparam = '';
             foreach ($method->getParameters() as $param) {
                 $mparam .= ', $' . $param;
                 if (isset($defval[$param])) {
                     $mparam .= '=\'' . str_replace("'", "\\'", $defval[$param]) . '\'';
                 }
             }
             $mparam = substr($mparam, 1);
         } else {
             $mparam = implode(', $', $method->getParameters());
             if ($mparam != '') {
                 $mparam = '$' . $mparam;
             }
         }
         $src[] = ' function ' . $method->name . ' (' . $mparam . '){';
         $limit = '';
         switch ($method->type) {
             case 'delete':
                 $src[] = '    $__query = \'DELETE FROM ' . $pTableRealNameEsc . ' \';';
                 $glueCondition = ' WHERE ';
                 break;
             case 'update':
                 $src[] = '    $__query = \'UPDATE ' . $pTableRealNameEsc . ' SET ';
                 $updatefields = $this->_getPropertiesBy('PrimaryFieldsExcludePk');
                 $sqlSet = '';
                 foreach ($method->getValues() as $propname => $value) {
                     if ($value[1]) {
                         foreach ($method->getParameters() as $param) {
                             $value[0] = str_replace('$' . $param, '\'.' . $this->_preparePHPExpr('$' . $param, $updatefields[$propname], true) . '.\'', $value[0]);
                         }
                         $sqlSet .= ', ' . $this->_encloseName($updatefields[$propname]->fieldName) . '= ' . $value[0];
                     } else {
                         $sqlSet .= ', ' . $this->_encloseName($updatefields[$propname]->fieldName) . '= ' . $this->_preparePHPValue($value[0], $updatefields[$propname]->datatype, false);
                     }
                 }
                 $src[] = substr($sqlSet, 1) . '\';';
                 $glueCondition = ' WHERE ';
                 break;
             case 'php':
                 $src[] = $method->getBody();
                 $src[] = '}';
                 break;
             case 'count':
                 if ($method->distinct != '') {
                     $prop = $this->_dataParser->getProperties();
                     $prop = $prop[$method->distinct];
                     $count = ' DISTINCT ' . $this->_encloseName($tables[$prop->table]['name']) . '.' . $this->_encloseName($prop->fieldName);
                 } else {
                     $count = '*';
                 }
                 $src[] = '    $__query = \'SELECT COUNT(' . $count . ') as c \'.$this->_fromClause.$this->_whereClause;';
                 $glueCondition = $sqlWhereClause != '' ? ' AND ' : ' WHERE ';
                 break;
             case 'selectfirst':
             case 'select':
             default:
                 if ($method->distinct != '') {
                     $select = '\'' . $this->_getSelectClause($method->distinct) . '\'';
                 } else {
                     $select = ' $this->_selectClause';
                 }
                 $src[] = '    $__query = ' . $select . '.$this->_fromClause.$this->_whereClause;';
                 $glueCondition = $sqlWhereClause != '' ? ' AND ' : ' WHERE ';
                 if ($method->type == 'select' && ($lim = $method->getLimit()) !== null) {
                     $limit = ', ' . $lim['offset'] . ', ' . $lim['count'];
                 }
         }
         if ($method->type == 'php') {
             continue;
         }
         $cond = $method->getConditions();
         $sqlCond = '';
         if ($cond !== null) {
             if ($method->type == 'delete' || $method->type == 'update') {
                 $sqlCond = $this->_buildConditions($cond, $primaryFields, $method->getParameters(), false);
             } else {
                 if ($method->type == 'count') {
                     $sqlCond = $this->_buildConditions($cond, $allField, $method->getParameters(), true);
                 } else {
                     $sqlCond = $this->_buildConditions($cond, $allField, $method->getParameters(), true, $method->getGroupBy());
                 }
             }
         } else {
             if ($method->type == 'select' || $method->type == 'selectfirst') {
                 $sqlCond = $this->_buildConditions(null, $allField, $method->getParameters(), true, $method->getGroupBy());
             }
         }
         if (trim($sqlCond) != '') {
             $src[] = '$__query .=\'' . $glueCondition . $sqlCond . "';";
         }
         switch ($method->type) {
             case 'delete':
             case 'update':
                 if ($method->eventBeforeEnabled || $method->eventAfterEnabled) {
                     $src[] = '   $args = func_get_args();';
                     $methname = $method->type == 'update' ? 'Update' : 'Delete';
                     if ($method->eventBeforeEnabled) {
                         $src[] = '   jEvent::notify("daoSpecific' . $methname . 'Before", array(\'dao\'=>$this->_daoSelector,\'method\'=>\'' . $method->name . '\', \'params\'=>$args));';
                     }
                     if ($method->eventAfterEnabled) {
                         $src[] = '   $result = $this->_conn->exec ($__query);';
                         $src[] = '   jEvent::notify("daoSpecific' . $methname . 'After", array(\'dao\'=>$this->_daoSelector,\'method\'=>\'' . $method->name . '\', \'params\'=>$args));';
                         $src[] = '   return $result;';
                     } else {
                         $src[] = '    return $this->_conn->exec ($__query);';
                     }
                 } else {
                     $src[] = '    return $this->_conn->exec ($__query);';
                 }
                 break;
             case 'count':
                 $src[] = '    $__rs = $this->_conn->query($__query);';
                 $src[] = '    $__res = $__rs->fetch();';
                 $src[] = '    return intval($__res->c);';
                 break;
             case 'selectfirst':
                 $src[] = '    $__rs = $this->_conn->limitQuery($__query,0,1);';
                 $src[] = '    $__rs->setFetchMode(8,\'' . $this->_DaoRecordClassName . '\');';
                 $src[] = '    return $__rs->fetch();';
                 break;
             case 'select':
             default:
                 if ($limit) {
                     $src[] = '    $__rs = $this->_conn->limitQuery($__query' . $limit . ');';
                 } else {
                     $src[] = '    $__rs = $this->_conn->query($__query);';
                 }
                 $src[] = '    $__rs->setFetchMode(8,\'' . $this->_DaoRecordClassName . '\');';
                 $src[] = '    return $__rs;';
         }
         $src[] = '}';
     }
     $src[] = '}';
     //end of class
     return implode("\n", $src);
 }