/**
  * Persist new or changed objects to the database container.
  *
  * Inserts or updates the database record representing this object and any
  * new or changed related object records.  Both aggregate and composite
  * related objects will be saved as appropriate, before or following the
  * save operation on the controlling instance.
  *
  * @param boolean|integer $cacheFlag Indicates if the saved object(s) should
  * be cached and optionally, by specifying an integer value, for how many
  * seconds before expiring.  Overrides the cacheFlag for the object(s).
  * @return boolean Returns true on success, false on failure.
  */
 public function save($cacheFlag = null)
 {
     if ($this->isLazy()) {
         $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, 'Attempt to save lazy object: ' . print_r($this->toArray('', true), 1));
         return false;
     }
     $result = true;
     $sql = '';
     $pk = $this->getPrimaryKey();
     $pkn = $this->getPK();
     $pkGenerated = false;
     if ($this->isNew()) {
         $this->setDirty();
     }
     if ($this->getOption(xPDO::OPT_VALIDATE_ON_SAVE)) {
         if (!$this->validate()) {
             return false;
         }
     }
     if (!$this->xpdo->getConnection(array(xPDO::OPT_CONN_MUTABLE => true))) {
         $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Could not get connection for writing data", '', __METHOD__, __FILE__, __LINE__);
         return false;
     }
     $this->_saveRelatedObjects();
     if (!empty($this->_dirty)) {
         $cols = array();
         $bindings = array();
         $updateSql = array();
         foreach (array_keys($this->_dirty) as $_k) {
             if (!array_key_exists($_k, $this->_fieldMeta)) {
                 continue;
             }
             if (isset($this->_fieldMeta[$_k]['generated'])) {
                 if (!$this->_new || !isset($this->_fields[$_k]) || empty($this->_fields[$_k])) {
                     $pkGenerated = true;
                     continue;
                 }
             }
             if ($this->_fieldMeta[$_k]['phptype'] === 'password') {
                 $this->_fields[$_k] = $this->encode($this->_fields[$_k], 'password');
             }
             $fieldType = PDO::PARAM_STR;
             $fieldValue = $this->_fields[$_k];
             if (in_array($this->_fieldMeta[$_k]['phptype'], array('datetime', 'timestamp')) && !empty($this->_fieldMeta[$_k]['attributes']) && $this->_fieldMeta[$_k]['attributes'] == 'ON UPDATE CURRENT_TIMESTAMP') {
                 $this->_fields[$_k] = strftime('%Y-%m-%d %H:%M:%S');
                 continue;
             } elseif ($fieldValue === null || $fieldValue === 'NULL') {
                 if ($this->_new) {
                     continue;
                 }
                 $fieldType = PDO::PARAM_NULL;
                 $fieldValue = null;
             } elseif (in_array($this->_fieldMeta[$_k]['phptype'], array('timestamp', 'datetime')) && in_array($fieldValue, $this->xpdo->driver->_currentTimestamps, true)) {
                 $this->_fields[$_k] = strftime('%Y-%m-%d %H:%M:%S');
                 continue;
             } elseif (in_array($this->_fieldMeta[$_k]['phptype'], array('date')) && in_array($fieldValue, $this->xpdo->driver->_currentDates, true)) {
                 $this->_fields[$_k] = strftime('%Y-%m-%d');
                 continue;
             } elseif ($this->_fieldMeta[$_k]['phptype'] == 'timestamp' && preg_match('/int/i', $this->_fieldMeta[$_k]['dbtype'])) {
                 $fieldType = PDO::PARAM_INT;
             } elseif (!in_array($this->_fieldMeta[$_k]['phptype'], array('string', 'password', 'datetime', 'timestamp', 'date', 'time', 'array', 'json', 'float'))) {
                 $fieldType = PDO::PARAM_INT;
             }
             if ($this->_new) {
                 $cols[$_k] = $this->xpdo->escape($_k);
                 $bindings[":{$_k}"]['value'] = $fieldValue;
                 $bindings[":{$_k}"]['type'] = $fieldType;
             } else {
                 $bindings[":{$_k}"]['value'] = $fieldValue;
                 $bindings[":{$_k}"]['type'] = $fieldType;
                 $updateSql[] = $this->xpdo->escape($_k) . " = :{$_k}";
             }
         }
         if ($this->_new) {
             $sql = "INSERT INTO {$this->_table} (" . implode(', ', array_values($cols)) . ") VALUES (" . implode(', ', array_keys($bindings)) . ")";
         } else {
             if ($pk && $pkn) {
                 if (is_array($pkn)) {
                     $iteration = 0;
                     $where = '';
                     foreach ($pkn as $k => $v) {
                         $vt = PDO::PARAM_INT;
                         if (in_array($this->_fieldMeta[$k]['phptype'], array('string', 'float'))) {
                             $vt = PDO::PARAM_STR;
                         }
                         if ($iteration) {
                             $where .= " AND ";
                         }
                         $where .= $this->xpdo->escape($k) . " = :{$k}";
                         $bindings[":{$k}"]['value'] = $this->_fields[$k];
                         $bindings[":{$k}"]['type'] = $vt;
                         $iteration++;
                     }
                 } else {
                     $pkn = $this->getPK();
                     $pkt = PDO::PARAM_INT;
                     if (in_array($this->_fieldMeta[$pkn]['phptype'], array('string', 'float'))) {
                         $pkt = PDO::PARAM_STR;
                     }
                     $bindings[":{$pkn}"]['value'] = $pk;
                     $bindings[":{$pkn}"]['type'] = $pkt;
                     $where = $this->xpdo->escape($pkn) . ' = :' . $pkn;
                 }
                 if (!empty($updateSql)) {
                     $sql = "UPDATE {$this->_table} SET " . implode(',', $updateSql) . " WHERE {$where}";
                 }
             }
         }
         if (!empty($sql) && ($criteria = new xPDOCriteria($this->xpdo, $sql))) {
             if ($criteria->prepare()) {
                 if (!empty($bindings)) {
                     $criteria->bind($bindings, true, false);
                 }
                 if ($this->xpdo->getDebug() === true) {
                     $this->xpdo->log(xPDO::LOG_LEVEL_DEBUG, "Executing SQL:\n{$sql}\nwith bindings:\n" . print_r($bindings, true));
                 }
                 $tstart = microtime(true);
                 if (!($result = $criteria->stmt->execute())) {
                     $this->xpdo->queryTime += microtime(true) - $tstart;
                     $this->xpdo->executedQueries++;
                     $errorInfo = $criteria->stmt->errorInfo();
                     $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error " . $criteria->stmt->errorCode() . " executing statement:\n" . $criteria->toSQL() . "\n" . print_r($errorInfo, true));
                     if (($errorInfo[1] == '1146' || $errorInfo[1] == '1') && $this->getOption(xPDO::OPT_AUTO_CREATE_TABLES)) {
                         if ($this->xpdo->getManager() && $this->xpdo->manager->createObjectContainer($this->_class) === true) {
                             $tstart = microtime(true);
                             if (!($result = $criteria->stmt->execute())) {
                                 $this->xpdo->queryTime += microtime(true) - $tstart;
                                 $this->xpdo->executedQueries++;
                                 $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error " . $criteria->stmt->errorCode() . " executing statement:\n{$sql}\n");
                             } else {
                                 $this->xpdo->queryTime += microtime(true) - $tstart;
                                 $this->xpdo->executedQueries++;
                             }
                         } else {
                             $this->xpdo->log(xPDO::LOG_LEVEL_ERROR, "Error " . $this->xpdo->errorCode() . " attempting to create object container for class {$this->_class}:\n" . print_r($this->xpdo->errorInfo(), true));
                         }
                     }
                 } else {
                     $this->xpdo->queryTime += microtime(true) - $tstart;
                     $this->xpdo->executedQueries++;
                 }
             } else {
                 $result = false;
             }
             if ($result) {
                 if ($pkn && !$pk) {
                     if ($pkGenerated) {
                         $this->_fields[$this->getPK()] = $this->xpdo->lastInsertId();
                     }
                     $pk = $this->getPrimaryKey();
                 }
                 if ($pk || !$this->getPK()) {
                     $this->_dirty = array();
                     $this->_validated = array();
                     $this->_new = false;
                 }
                 $callback = $this->getOption(xPDO::OPT_CALLBACK_ON_SAVE);
                 if ($callback && is_callable($callback)) {
                     call_user_func($callback, array('className' => $this->_class, 'criteria' => $criteria, 'object' => $this));
                 }
                 if ($this->xpdo->_cacheEnabled && $pk && ($cacheFlag || $cacheFlag === null && $this->_cacheFlag)) {
                     $cacheKey = $this->xpdo->newQuery($this->_class, $pk, $cacheFlag);
                     if (is_bool($cacheFlag)) {
                         $expires = 0;
                     } else {
                         $expires = intval($cacheFlag);
                     }
                     $this->xpdo->toCache($cacheKey, $this, $expires, array('modified' => true));
                 }
             }
         }
     }
     $this->_saveRelatedObjects();
     if ($result) {
         $this->_dirty = array();
         $this->_validated = array();
     }
     return $result;
 }
Exemple #2
0
$disThread = $modx->getTableName('disThread');
$bindings = array();
$sql = "INSERT INTO {$disRead} ({$modx->getSelectColumns('disThreadRead', '', '', array('user', 'board', 'thread'))}) ";
$cSub = $modx->newQuery('disThread');
$cSub->select(array(1 => "({$userId})", $modx->getSelectColumns('disThread', 'disThread', '', array('board', 'id'))));
if (!empty($scriptProperties['lastLogin'])) {
    $cSub->where(array('post_last_on:>=' => strtotime($scriptProperties['lastLogin'])));
    if ($scriptProperties['ts'] !== false) {
        $cSub->where(array('post_last_on:<' => $scriptProperties['ts']));
    }
} else {
    if (!empty($scriptProperties['replies'])) {
        $cSub->innerJoin('disThreadParticipant', 'Participants', array("{$modx->escape('Participants')}.{$modx->escape('user')} = {$userId}", "{$modx->escape('Participants')}.{$modx->escape('thread')} = {$modx->escape('disThread')}.{$modx->escape('id')}"));
        $cSub->where(array('author_last:!=' => $userId));
    }
}
$cSub->where(array("{$modx->escape('disThread')}.{$modx->escape('id')} NOT IN ({$disReadSub->toSQL()})", 'private' => 0));
$cSub->prepare();
$sql .= $cSub->toSQL();
$criteria = new xPDOCriteria($modx, $sql);
if ($criteria->prepare()) {
    if (!empty($bindings)) {
        $criteria->bind($bindings, true, false);
    }
    if (!$criteria->stmt->execute()) {
        $errorInfo = $criteria->stmt->errorInfo();
        $modx->log(xPDO::LOG_LEVEL_ERROR, "Error " . $criteria->stmt->errorCode() . " executing statement:\n" . $criteria->toSQL() . "\n" . print_r($errorInfo, true));
        return false;
    }
}
return true;