/** * {@inheritdoc} * * @throws \Titon\Db\Exception\UnsupportedQueryStatementException */ public function buildStatement(Query $query) { $type = $query->getType(); $method = 'build' . ucfirst($type); $dialect = $this->getDialect(); if (!method_exists($dialect, $method)) { throw new UnsupportedQueryStatementException(sprintf('Query statement %s does not exist or has not been implemented', $type)); } return $this->getConnection()->prepare(call_user_func([$dialect, $method], $query)); }
/** * Before a save occurs, generate a unique slug using another field as the base. * If no data exists, or the base doesn't exist, or the slug is already set, exit early. * * @param \Titon\Event\Event $event * @param \Titon\Db\Query $query * @param int|int[] $id * @param array $data * @return bool */ public function preSave(Event $event, Query $query, $id, array &$data) { $config = $this->allConfig(); if (empty($data) || empty($data[$config['field']]) || !empty($data[$config['slug']])) { return true; } else { if ($query->getType() === Query::UPDATE && !$config['onUpdate']) { return true; } } $slug = static::slugify($data[$config['field']]); // Leave a gap of 3 to account for the appended numbers if (mb_strlen($slug) > $config['length'] - 3) { $slug = mb_substr($slug, 0, $config['length'] - 3); } if ($config['unique']) { $slug = $this->makeUnique($id, $slug); } $data[$config['slug']] = $slug; return true; }
/** * Add a new compound query. Only select queries can be used with compounds. * * @param string $type * @param \Titon\Db\Query $query * @return $this * @throws \Titon\Db\Exception\InvalidQueryException */ protected function _addCompound($type, Query $query) { if ($query->getType() !== self::SELECT) { throw new InvalidQueryException(sprintf('Only a select query can be used with %s', $type)); } $query->attribute('compound', $type); $this->_compounds[] = $query; return $this; }
/** * Format the fields values structure depending on the type of query. * * @param \Titon\Db\Query $query * @return string */ public function formatValues(Query $query) { $fields = $query->getData(); switch ($query->getType()) { case Query::INSERT: return sprintf($this->getClause(self::GROUP), implode(', ', array_fill(0, count($fields), '?'))); break; case Query::MULTI_INSERT: $value = sprintf($this->getClause(self::GROUP), implode(', ', array_fill(0, count($fields[0]), '?'))); return implode(', ', array_fill(0, count($fields), $value)); break; } return ''; }
/** * Before an insert, determine the correct left and right using the parent or root node as a base. * Do not shift the nodes until postSave() just in case the insert fails. * * Before an update, remove the left and right fields so that the tree cannot be modified. * Use moveUp(), moveDown(), moveTo() or reOrder() to update existing nodes. * * @param \Titon\Event\Event $event * @param \Titon\Db\Query $query * @param int|int[] $id * @param array $data * @return bool */ public function preSave(Event $event, Query $query, $id, array &$data) { if (!$this->getConfig('onSave')) { return true; } $parent = $this->getConfig('parentField'); $left = $this->getConfig('leftField'); $right = $this->getConfig('rightField'); // Append left and right during create if ($query->getType() === Query::INSERT) { $indexes = []; // Is a child if (isset($data[$parent])) { if ($node = $this->getNode($data[$parent])) { $parentRight = $node[$right]; // Save index for moving postSave $this->_saveIndex = $parentRight; $indexes = [$left => $parentRight, $right => $parentRight + 1]; } } // Fallback to root if (empty($indexes)) { $node = $this->getLastNode(); $rootRight = $node[$right]; $indexes = [$left => $rootRight + 1, $right => $rootRight + 2]; } $data = $indexes + $data; } return true; }
/** * Return a count of how many rows were affected by the query. * * @param \Titon\Db\Query $query * @param array $options * @return int */ public function save(Query $query, array $options = []) { $type = $query->getType(); if ($type === Query::DELETE) { return $this->_processDelete($query, $options); } else { if ($type === Query::INSERT) { return $this->_processCreate($query, $options); } else { if ($type === Query::UPDATE) { return $this->_processUpdate($query, $options); } } } // No processing or events, just execute it directly return $this->getDriver()->executeQuery($query)->save(); }
/** * Append the current timestamp to the data. * * @param \Titon\Event\Event $event * @param \Titon\Db\Query $query * @param int|int[] $id * @param array $data * @return bool */ public function preSave(Event $event, Query $query, $id, array &$data) { $data[$this->getConfig($query->getType() === Query::UPDATE ? 'updateField' : 'createField')] = time(); return true; }